diff --git a/Html/addPlugin.html b/Html/addPlugin.html new file mode 100644 index 0000000000..820319091e --- /dev/null +++ b/Html/addPlugin.html @@ -0,0 +1,80 @@ + + + + + + +
+ +
+
+

+ Plugin Catalog +

+
+

+

+ +

+ +
+

Install

+

+

+

+ + +

+ +

+ +

+
+
+ +
+ + +
+

Developer Info

+

+ +
+ +
+

Revision History

+
+
+
+ +
+
+ +
+ + diff --git a/Html/advanced.html b/Html/advanced.html new file mode 100644 index 0000000000..d9a7f78cc9 --- /dev/null +++ b/Html/advanced.html @@ -0,0 +1,56 @@ + + + + Advanced + + +
+ +
+
+
+ +
    +
  • + + +
  • +
  • + + +
  • + +
  • + + +
    + When enabled, developer tools will be available from the system tray. +
    +
  • +
  • + + +
  • +
  • + + +
  • +
+ +
+
+
+ + +
+ + diff --git a/Html/advancedMetadata.html b/Html/advancedMetadata.html new file mode 100644 index 0000000000..60e02ba3c0 --- /dev/null +++ b/Html/advancedMetadata.html @@ -0,0 +1,43 @@ + + + + Metadata + + +
+ +
+ +
+ + +
+
    +
  • + +
    +
  • +
  • + + +
  • +
+
+
+ +
+ + +
+ + diff --git a/Html/css/images/bg.png b/Html/css/images/bg.png new file mode 100644 index 0000000000..d1e8358715 Binary files /dev/null and b/Html/css/images/bg.png differ diff --git a/Html/css/images/checkMarkGreen.png b/Html/css/images/checkMarkGreen.png new file mode 100644 index 0000000000..c5cd1c7d4c Binary files /dev/null and b/Html/css/images/checkMarkGreen.png differ diff --git a/Html/css/images/checkmarkblack.png b/Html/css/images/checkmarkblack.png new file mode 100644 index 0000000000..d825a1d761 Binary files /dev/null and b/Html/css/images/checkmarkblack.png differ diff --git a/Html/css/images/clients/android.png b/Html/css/images/clients/android.png new file mode 100644 index 0000000000..88e3b93e4f Binary files /dev/null and b/Html/css/images/clients/android.png differ diff --git a/Html/css/images/clients/html5.png b/Html/css/images/clients/html5.png new file mode 100644 index 0000000000..2fdbe426ad Binary files /dev/null and b/Html/css/images/clients/html5.png differ diff --git a/Html/css/images/clients/ios.png b/Html/css/images/clients/ios.png new file mode 100644 index 0000000000..1429af5dc9 Binary files /dev/null and b/Html/css/images/clients/ios.png differ diff --git a/Html/css/images/clients/mb.png b/Html/css/images/clients/mb.png new file mode 100644 index 0000000000..c641c0652c Binary files /dev/null and b/Html/css/images/clients/mb.png differ diff --git a/Html/css/images/clients/win8.png b/Html/css/images/clients/win8.png new file mode 100644 index 0000000000..7ee409ff82 Binary files /dev/null and b/Html/css/images/clients/win8.png differ diff --git a/Html/css/images/clients/windowsphone.png b/Html/css/images/clients/windowsphone.png new file mode 100644 index 0000000000..1a31e55f61 Binary files /dev/null and b/Html/css/images/clients/windowsphone.png differ diff --git a/Html/css/images/clients/windowsrt.png b/Html/css/images/clients/windowsrt.png new file mode 100644 index 0000000000..6a91da5e62 Binary files /dev/null and b/Html/css/images/clients/windowsrt.png differ diff --git a/Html/css/images/cloudNetwork.png b/Html/css/images/cloudNetwork.png new file mode 100644 index 0000000000..2f917c1a0b Binary files /dev/null and b/Html/css/images/cloudNetwork.png differ diff --git a/Html/css/images/currentUserDefaultBlack.png b/Html/css/images/currentUserDefaultBlack.png new file mode 100644 index 0000000000..fff3f51a23 Binary files /dev/null and b/Html/css/images/currentUserDefaultBlack.png differ diff --git a/Html/css/images/currentUserDefaultWhite.png b/Html/css/images/currentUserDefaultWhite.png new file mode 100644 index 0000000000..acfa26e9de Binary files /dev/null and b/Html/css/images/currentUserDefaultWhite.png differ diff --git a/Html/css/images/defaultCollectionImage.png b/Html/css/images/defaultCollectionImage.png new file mode 100644 index 0000000000..d1e862a694 Binary files /dev/null and b/Html/css/images/defaultCollectionImage.png differ diff --git a/Html/css/images/donatepp.png b/Html/css/images/donatepp.png new file mode 100644 index 0000000000..c99d2ea135 Binary files /dev/null and b/Html/css/images/donatepp.png differ diff --git a/Html/css/images/home.png b/Html/css/images/home.png new file mode 100644 index 0000000000..216608e42c Binary files /dev/null and b/Html/css/images/home.png differ diff --git a/Html/css/images/iossplash.png b/Html/css/images/iossplash.png new file mode 100644 index 0000000000..6467ebe7d3 Binary files /dev/null and b/Html/css/images/iossplash.png differ diff --git a/Html/css/images/itemDetails/audioDefault.png b/Html/css/images/itemDetails/audioDefault.png new file mode 100644 index 0000000000..4e59c995ed Binary files /dev/null and b/Html/css/images/itemDetails/audioDefault.png differ diff --git a/Html/css/images/itemDetails/gameDefault.png b/Html/css/images/itemDetails/gameDefault.png new file mode 100644 index 0000000000..b08ade6e4a Binary files /dev/null and b/Html/css/images/itemDetails/gameDefault.png differ diff --git a/Html/css/images/itemDetails/videoDefault.png b/Html/css/images/itemDetails/videoDefault.png new file mode 100644 index 0000000000..b315bdf1ae Binary files /dev/null and b/Html/css/images/itemDetails/videoDefault.png differ diff --git a/Html/css/images/leftArrowBlack.png b/Html/css/images/leftArrowBlack.png new file mode 100644 index 0000000000..91e4a2571e Binary files /dev/null and b/Html/css/images/leftArrowBlack.png differ diff --git a/Html/css/images/leftArrowWhite.png b/Html/css/images/leftArrowWhite.png new file mode 100644 index 0000000000..9f3140b17f Binary files /dev/null and b/Html/css/images/leftArrowWhite.png differ diff --git a/Html/css/images/logindefault.png b/Html/css/images/logindefault.png new file mode 100644 index 0000000000..9e7311e4fc Binary files /dev/null and b/Html/css/images/logindefault.png differ diff --git a/Html/css/images/mblogoblackfull.png b/Html/css/images/mblogoblackfull.png new file mode 100644 index 0000000000..340f12d9df Binary files /dev/null and b/Html/css/images/mblogoblackfull.png differ diff --git a/Html/css/images/mblogowhitefull.png b/Html/css/images/mblogowhitefull.png new file mode 100644 index 0000000000..48c8f72d39 Binary files /dev/null and b/Html/css/images/mblogowhitefull.png differ diff --git a/Html/css/images/media/nextTrack.png b/Html/css/images/media/nextTrack.png new file mode 100644 index 0000000000..173734fe00 Binary files /dev/null and b/Html/css/images/media/nextTrack.png differ diff --git a/Html/css/images/media/pause.png b/Html/css/images/media/pause.png new file mode 100644 index 0000000000..1f347cdef9 Binary files /dev/null and b/Html/css/images/media/pause.png differ diff --git a/Html/css/images/media/play.png b/Html/css/images/media/play.png new file mode 100644 index 0000000000..0a0529f2f7 Binary files /dev/null and b/Html/css/images/media/play.png differ diff --git a/Html/css/images/media/playCircle.png b/Html/css/images/media/playCircle.png new file mode 100644 index 0000000000..6d2ffd3413 Binary files /dev/null and b/Html/css/images/media/playCircle.png differ diff --git a/Html/css/images/media/previousTrack.png b/Html/css/images/media/previousTrack.png new file mode 100644 index 0000000000..f5b47417f2 Binary files /dev/null and b/Html/css/images/media/previousTrack.png differ diff --git a/Html/css/images/media/stop.png b/Html/css/images/media/stop.png new file mode 100644 index 0000000000..ea6bcb96e3 Binary files /dev/null and b/Html/css/images/media/stop.png differ diff --git a/Html/css/images/movieFolder.png b/Html/css/images/movieFolder.png new file mode 100644 index 0000000000..ac52cab359 Binary files /dev/null and b/Html/css/images/movieFolder.png differ diff --git a/Html/css/images/notifications/cancelled.png b/Html/css/images/notifications/cancelled.png new file mode 100644 index 0000000000..319fd7faba Binary files /dev/null and b/Html/css/images/notifications/cancelled.png differ diff --git a/Html/css/images/notifications/done.png b/Html/css/images/notifications/done.png new file mode 100644 index 0000000000..b64e558cde Binary files /dev/null and b/Html/css/images/notifications/done.png differ diff --git a/Html/css/images/notifications/download.png b/Html/css/images/notifications/download.png new file mode 100644 index 0000000000..780f72dcb1 Binary files /dev/null and b/Html/css/images/notifications/download.png differ diff --git a/Html/css/images/notifications/error.png b/Html/css/images/notifications/error.png new file mode 100644 index 0000000000..c6b5693c4e Binary files /dev/null and b/Html/css/images/notifications/error.png differ diff --git a/Html/css/images/notifications/info.png b/Html/css/images/notifications/info.png new file mode 100644 index 0000000000..fb724718fd Binary files /dev/null and b/Html/css/images/notifications/info.png differ diff --git a/Html/css/images/premiumflag.png b/Html/css/images/premiumflag.png new file mode 100644 index 0000000000..e34fe810e5 Binary files /dev/null and b/Html/css/images/premiumflag.png differ diff --git a/Html/css/images/registerpp.png b/Html/css/images/registerpp.png new file mode 100644 index 0000000000..e5ecaa8639 Binary files /dev/null and b/Html/css/images/registerpp.png differ diff --git a/Html/css/images/rightArrow.png b/Html/css/images/rightArrow.png new file mode 100644 index 0000000000..f5771d4199 Binary files /dev/null and b/Html/css/images/rightArrow.png differ diff --git a/Html/css/images/stars.png b/Html/css/images/stars.png new file mode 100644 index 0000000000..4a31313f09 Binary files /dev/null and b/Html/css/images/stars.png differ diff --git a/Html/css/images/suppbadge.png b/Html/css/images/suppbadge.png new file mode 100644 index 0000000000..9295ae07dc Binary files /dev/null and b/Html/css/images/suppbadge.png differ diff --git a/Html/css/images/toolsBlack.png b/Html/css/images/toolsBlack.png new file mode 100644 index 0000000000..233e7ea17b Binary files /dev/null and b/Html/css/images/toolsBlack.png differ diff --git a/Html/css/images/toolsWhite.png b/Html/css/images/toolsWhite.png new file mode 100644 index 0000000000..c55c16766e Binary files /dev/null and b/Html/css/images/toolsWhite.png differ diff --git a/Html/css/images/touchicon.png b/Html/css/images/touchicon.png new file mode 100644 index 0000000000..c476cbb35c Binary files /dev/null and b/Html/css/images/touchicon.png differ diff --git a/Html/css/images/touchicon114.png b/Html/css/images/touchicon114.png new file mode 100644 index 0000000000..7099b59705 Binary files /dev/null and b/Html/css/images/touchicon114.png differ diff --git a/Html/css/images/touchicon72.png b/Html/css/images/touchicon72.png new file mode 100644 index 0000000000..6802032703 Binary files /dev/null and b/Html/css/images/touchicon72.png differ diff --git a/Html/css/images/userFlyoutDefault.png b/Html/css/images/userFlyoutDefault.png new file mode 100644 index 0000000000..f27a4bcb34 Binary files /dev/null and b/Html/css/images/userFlyoutDefault.png differ diff --git a/Html/css/site.css b/Html/css/site.css new file mode 100644 index 0000000000..c9b2089c73 --- /dev/null +++ b/Html/css/site.css @@ -0,0 +1,897 @@ +@font-face { + font-family: "Open Sans"; + font-style: normal; + font-weight: 700; + src: local("Open Sans Bold"), local("OpenSans-Bold"), url(http://themes.googleusercontent.com/static/fonts/opensans/v6/k3k702ZOKiLJc3WVjuplzJ1r3JsPcQLi8jytr04NNhU.woff) format('woff'); +} + +@font-face { + font-family: "Open Sans"; + font-style: normal; + font-weight: 300; + src: local("Open Sans Light"), local("OpenSans-Light"), url(http://themes.googleusercontent.com/static/fonts/opensans/v6/DXI1ORHCpsQm3Vp6mXoaTZ1r3JsPcQLi8jytr04NNhU.woff) format('woff'); +} + +@font-face { + font-family: "Open Sans"; + font-style: normal; + font-weight: 800; + src: local("Open Sans Extrabold"), local("OpenSans-Extrabold"), url(http://themes.googleusercontent.com/static/fonts/opensans/v6/EInbV5DfGHOiMmvb1Xr-hp1r3JsPcQLi8jytr04NNhU.woff) format('woff'); +} + +@font-face { + font-family: "Open Sans"; + font-style: normal; + font-weight: 400; + src: local("Open Sans"), local("OpenSans"), url(http://themes.googleusercontent.com/static/fonts/opensans/v6/K88pR3goAWT7BTt32Z01mz8E0i7KZn-EPnyo3HZu7kw.woff) format('woff'); +} + +body { + overflow-y: scroll!important; +} + +h1 { + font-family: 'Segoe UI Light', 'Open Sans', Arial, Helvetica, sans-serif; + font-weight: 200; + font-size: 32pt; +} + +.toolsSidebar h1 { + font-size: 42pt; +} + +.ui-loader h1 { + font-weight: bold; + font-family: Arial; +} + +h2 { + font-family: 'Segoe UI Semiight', 'Open Sans', Arial, Helvetica, sans-serif; + font-weight: 400; + font-size: 22pt; +} + +pre, textarea.pre { + display: block; + padding: 8.5px; + font-size: 12.025px; + line-height: 18px; + word-break: break-all; + word-wrap: break-word; + white-space: pre; + white-space: pre-wrap; + background-color: #f5f5f5; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + color: #000; +} + +.type-interior h2 { + color: #1B58B8; +} + +/* + Page / Base styles + */ +.page { + background: #f2f2f2; + background-attachment: fixed; +} + +.libraryPage { + background: #1d1d1d url(images/bg.png) top left repeat-x; + background: #262626!important; + background-attachment: fixed!important; +} + + .libraryPage .interiorLink { + color: #2489ce; + font-weight: bold; + } + +/* + Header + */ +.header { + padding: 10px 0 10px 10px; +} + +.imgLogo { + height: 45px; +} + + +.ui-popup-container { + z-index: 99999; +} + +.headerButtons { + float: right; + position: absolute; + top: 10px; + right: 10px; +} + +.header .imageLink { + display: inline-block; +} + +.imageLink + .imageLink { + margin-left: 30px; +} + +.header .imageLink img { + height: 32px; + vertical-align: middle; +} + +.btnCurrentUser { + text-decoration: none; +} + +.currentUsername { + margin-right: 7px; + font-size: 20px; + color: #000; + position: relative; + top: 4px; +} + +.libraryPage .currentUsername { + color: #fff; +} + +h1 .imageLink { + margin-left: 15px; +} + + h1 .imageLink img { + height: 32px; + } + +.imageLink:hover { + opacity: .5; +} + +.type-home h1 { + margin-top: 1.25em; + margin-bottom: 10px; + padding-bottom: 5px; + font-weight: normal; + border-bottom: 1px solid #777; +} + +.libraryPage .ui-content > h1:first-child { + margin-top: 0; +} + +.pageTitle { + margin-top: 0; +} + +.imageButton { + background: transparent; + border: 0; + padding: 0; + cursor: pointer; + cursor: hand; +} + + .imageButton:hover { + opacity: .5; + } + + .imageButton[disabled], .imageButton[disabled]:hover { + opacity: .3!important; + cursor: default; + } + +/* + Forms + */ +form, .readOnlyContent { + max-width: 600px; +} + +.fieldDescription { + font-size: 11px; + padding-left: 5px; +} + +.ulForm { + margin-bottom: 20px!important; +} + + .ulForm li:not(.ui-li-divider) { + background: none; + border-top: none; + border-bottom: none; + } + +.popup .ulForm { + margin-bottom: 0!important; +} + +.popup .ui-content { + padding: 20px; +} + +.content-secondary { + z-index: 99996; + background: #262626; + border: 0; + margin-top: 40px; +} + + .content-secondary h1 { + margin: 0; + padding: 20px 0 20px 30px; + color: #fff; + } + +.sidebarLinks a { + display: block; + padding: 12px 15px 12px 30px; + text-decoration: none; + color: #fff!important; + text-shadow: none!important; + font-weight: normal!important; + font-size: 17px; +} + + .sidebarLinks a:hover { + background: #f2f2f2; + color: #000!important; + } + + .sidebarLinks a.selectedSidebarLink { + background: #2572EB!important; + color: #fff!important; + } + +/* Tabs (e.g. advanced metadata page) */ +.localnav { + margin-bottom: 40px!important; +} + + .localnav + form { + margin-top: -10px; + } + +.page > .ui-content { + padding-bottom: 100px; +} + +@media all and (min-width: 650px) { + + .imgLogo { + height: 60px; + } + + .header { + padding-left: 30px; + padding-top: 20px; + padding-bottom: 15px; + } + + .headerButtons { + top: 20px; + right: 30px; + } + + .localnav .ui-btn-inner { + font-size: 16px; + } + + .libraryPage .ui-content { + padding-right: 50px; + padding-left: 50px; + } + + .type-interior > .ui-content { + padding-right: 0; + padding-left: 0; + padding-top: 0; + overflow: hidden; + } + + .content-secondary { + text-align: left; + width: 45%; + position: fixed; + top: 0; + left: 0; + bottom: 0; + margin: 0; + } + + .content-primary { + width: 45%; + float: right; + padding: 0 6% 3em 0; + margin: 0; + } + + .content-primary ul:first-child { + margin-top: 0; + } +} + +@media all and (min-width: 750px) { + + .content-secondary { + width: 34%; + } + + .content-primary { + width: 56%; + } +} + +@media all and (min-width: 1200px) { + + + .content-secondary { + width: 30%; + } + + .content-primary { + width: 60%; + } +} + +@media all and (min-width: 1440px) { + + + .content-secondary { + width: 25%; + } + + .content-primary { + width: 65%; + } +} + +@media all and (min-width: 1920px) { + + + .content-secondary { + width: 20%; + } + + .content-primary { + width: 70%; + } +} + +/* + Media Library Page + */ +.mediaFolderButtons { + margin-top: 10px; +} + +.mediaFolderLocations { + margin: 1em .25em!important; +} + +.mediaLocationsHeader { + padding-top: .75em!important; + padding-bottom: .75em!important; +} + + .mediaLocationsHeader .ui-btn { + position: absolute; + right: 3px; + margin-top: 0!important; + margin-bottom: 0!important; + top: 6px; + } + +#divVirtualFolders .ui-btn-inner, .mediaLocationsHeader, #divVirtualFolders .ui-btn-text { + font-size: 14px; +} + +#ulDirectoryPickerList a { + padding-top: .4em; + padding-bottom: .4em; + font-size: 15px; +} + +/* + Plugin updates Page + */ +#pluginUpdatesForm table { + width: 100%; +} + +#pluginUpdatesForm td + td { + text-align: center; +} + + +/* + List Vew Items + */ + +.posterViewItem { + display: inline-block; + margin: 5px; + text-align: center; + font-size: 15px; + padding: 0; + position: relative; + padding-bottom: 28px; +} + + .posterViewItem a { + color: white!important; + font-weight: normal!important; + text-decoration: none; + } + + .posterViewItem img { + max-width: 155px; + max-height: 148px; + vertical-align: bottom; + } + +.premiumBanner img { + position: absolute; + text-align: right; + top: 0; + right: 0; + width: 75px!important; + height: 75px!important; + max-width: 75px!important; + max-height: 75px!important; +} + +.posterViewItemText { + text-overflow: ellipsis; + overflow: hidden; + text-wrap: none; + white-space: nowrap; + margin: 0; + padding: 4px 2px 0; + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 24px; + background: #181818; + text-shadow: none; +} + +.posterViewItem:hover, .userItem:hover { + -moz-box-shadow: 0 0 20px 3px #2572EB; + -webkit-box-shadow: 0 0 20px 3px #2572EB; + box-shadow: 0 0 20px 3px #2572EB; +} + +@media all and (min-width: 750px) { + + .posterViewItem { + font-size: 16px; + padding-bottom: 29px; + } + + .posterViewItemText { + padding-top: 5px; + } + + .posterViewItem img { + max-width: 190px; + max-height: 190px; + } +} + +@media all and (min-width: 1200px) { + + .posterViewItem { + font-size: 17px; + } + + .posterViewItem img { + max-width: 280px; + max-height: 250px; + } +} + +@media all and (min-width: 1920px) { + + .posterViewItem { + font-size: 19px; + padding-bottom: 33px; + } + + .posterViewItemText { + height: 28px; + } + + .posterViewItem img { + max-width: 352px; + max-height: 300px; + } +} + +.userItem { + display: inline-block; + margin: 5px; + font-size: 15px; + text-align: left; +} + +.userItemImage { + height: 100px; + width: 100px; + vertical-align: bottom; +} + +.userItemContent { + display: inline-block; + height: 100px; + width: 180px; + float: right; + text-shadow: none; + font-family: 'Segoe UI Light', 'Open Sans', Arial; +} + +.userItemContentInner { + padding: 15px 5px 5px 10px; + color: #fff; +} + +.userItemHeader { + margin: 0 0 10px; + font-size: 16px; + text-overflow: ellipsis; + overflow: hidden; + text-wrap: avoid; + font-family: 'Segoe UI Semilight', 'Open Sans', Arial; +} + +@media all and (min-width: 750px) { + + .userItem { + font-size: 16px; + } + + .userItemContentInner { + padding: 30px 20px 20px; + } + + .userItemImage { + height: 140px; + width: 140px; + } + + .userItemContent { + height: 140px; + width: 210px; + } + + .userItemHeader { + font-size: 26px; + } +} + +@media all and (min-width: 1200px) { + + .userItem { + font-size: 18px; + } + + .userItemImage { + height: 180px; + width: 180px; + } + + .userItemContent { + height: 180px; + width: 270px; + } + + .userItemHeader { + font-size: 32px; + } +} + +@media all and (min-width: 1920px) { + + .userItem { + font-size: 20px; + } + + .userItemImage { + height: 240px; + width: 240px; + } + + .userItemContent { + height: 240px; + width: 360px; + } + + .userItemHeader { + font-size: 40px; + } +} + +/* Startup wizard */ +.wizardPage { + background: #e2e2e2; +} + +.wizardContent { + max-width: 800px; + padding: .5em 2em 1em; + margin: 0 auto; + background: #f2f2f2; +} + +.wizardNavigation { + text-align: right; +} + +.wizardContent form { + max-width: 100%; +} + +.wizardContent p { + margin: 2em 0; +} + +.wizardContent h2 img { + height: 35px; + vertical-align: middle; + margin-right: .5em; + position: relative; + top: -3px; +} + +/* User Image */ +.imageDropZone { + border: 2px dashed #bbb; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; + padding: 25px; + text-align: center; + color: #bbb; +} + +/* Dashboard home */ +.tblConnections td { + padding: .5em 0 .5em 1.25em; +} + + .tblConnections td:first-child { + padding-left: 0; + } + +.tblConnections img { + height: 50px; +} + +.clientNowPlayingImage { + border-radius: 5px; + border: 2px solid #ccc; +} + +/* Footer */ +#footer { + background: #5a5a5a; + position: fixed; + bottom: -2px; + left: -2px; + right: -2px; + z-index: 99997; +} + +.footerNotification { + text-shadow: none; + padding: .5em 1em; + margin: 0; + font-weight: normal; + border-top: 1px solid #999; +} + +.notificationIcon { + height: 24px; + margin-right: 1em; + vertical-align: middle; +} + +/* + * Gradient Shadow + */ + +/* All HTML5 progress enabled browsers */ +progress { + /* Turns off styling - not usually needed, but good to know. */ + appearance: none; + -moz-appearance: none; + -webkit-appearance: none; + /* gets rid of default border in Firefox and Opera. */ + border: solid #cccccc 2px; + border-radius: 4px; + margin: 0; +} + + /* Polyfill */ + progress[role]:after { + background-image: none; /* removes default background from polyfill */ + } + +/* + * Background of the progress bar background + */ + +/* Firefox and Polyfill */ +progress { + background: #cccccc !important; /* !important only needed in polyfill */ +} + + /* Chrome */ + progress::-webkit-progress-bar { + background: #cccccc; + } + + /* + * Background of the progress bar value + */ + + /* Firefox */ + progress::-moz-progress-bar { + border-radius: 5px; + background-image: -moz-linear-gradient( center bottom, rgb(43,194,83) 37%, rgb(84,240,84) 69% ); + } + + /* Chrome */ + progress::-webkit-progress-value { + border-radius: 5px; + background-image: -webkit-gradient( linear, left bottom, left top, color-stop(0, rgb(43,194,83)), color-stop(1, rgb(84,240,84)) ); + background-image: -webkit-linear-gradient( center bottom, rgb(43,194,83) 37%, rgb(84,240,84) 69% ); + } + + /* Polyfill */ + progress[aria-valuenow]:before { + border-radius: 5px; + background-image: -moz-linear-gradient( center bottom, rgb(43,194,83) 37%, rgb(84,240,84) 69% ); + background-image: -ms-linear-gradient( center bottom, rgb(43,194,83) 37%, rgb(84,240,84) 69% ); + background-image: -o-linear-gradient( center bottom, rgb(43,194,83) 37%, rgb(84,240,84) 69% ); + } + +/* Detail Page*/ + +.itemDetailImage { + max-width: 100%; + max-height: 400px; +} + +.itemImageBlock { + vertical-align: top; +} + +.itemDetailBlock { + vertical-align: top; + padding-top: 1em; +} + + .itemDetailBlock p { + margin-top: 0; + } + +.starRating { + background-image: url(data:image/png;base64,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); + background-position: left center; + background-repeat: no-repeat; + width: 24px; + height: 20px; + display: inline-block; + background-size: cover; +} + +.galleryImage { + width: 120px; + display: inline-block; + margin: 5px; +} + +.halfStarRating { + background-position: center center; +} + +.emptyStarRating { + background-position: right center; +} + +@media all and (min-width: 650px) { + .itemImageBlock { + display: inline-block; + } + + .itemDetailImage, .itemImageBlock { + max-width: 220px; + } + + .itemDetailBlock { + padding-top: 0; + display: inline-block; + width: 45%; + padding-left: 20px; + max-width: 800px; + } + + .galleryImage { + width: 150px; + } +} + +@media all and (min-width: 750px) { + + .itemDetailImage, .itemImageBlock { + max-width: 300px; + } + + .itemDetailBlock { + padding-left: 30px; + } +} + + +@media all and (min-width: 1200px) { + + .itemDetailImage, .itemImageBlock { + max-width: 400px; + } + + .itemDetailBlock { + width: 55%; + } + + .galleryImage { + width: 200px; + } +} + +/* Now playing bar */ +#nowPlayingBar { + padding: 10px 20px 8px; + border-top: 1px solid #5490CC; +} + +.mediaButton { + margin: 0 20px 0 0; + display: inline-block; +} + +#mediaElement { + margin-right: 20px; + display: inline-block; + position: relative; +} + +.mediaButton img { + height: 28px; +} + +.itemVideo { + position: absolute; + z-index: 99998; + height: auto; + width: 180px; + bottom: -5px; +} + +@media all and (min-width: 650px) { + + .itemVideo { + width: 270px; + } +} diff --git a/Html/dashboard.html b/Html/dashboard.html new file mode 100644 index 0000000000..805c9c45e8 --- /dev/null +++ b/Html/dashboard.html @@ -0,0 +1,52 @@ + + + + Dashboard + + +
+ +
+
+
+
+

Server Information

+
+

+ Version +

+ + +
+
+ + + +
+

Active Connections

+
+
+
+ +
+

Running Tasks

+
+
+

Manage Scheduled Tasks

+
+
+
+
+
+ + diff --git a/Html/editUser.html b/Html/editUser.html new file mode 100644 index 0000000000..85ae14132e --- /dev/null +++ b/Html/editUser.html @@ -0,0 +1,63 @@ + + + + + + +
+ +
+
+ +
+
    +
  • + + +
  • + + +
+

Video Playback Settings

+
    +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
+
+
+
+ +
+ + diff --git a/Html/favicon.ico b/Html/favicon.ico new file mode 100644 index 0000000000..1541dabdc4 Binary files /dev/null and b/Html/favicon.ico differ diff --git a/Html/index.html b/Html/index.html new file mode 100644 index 0000000000..960f49533a --- /dev/null +++ b/Html/index.html @@ -0,0 +1,33 @@ + + + + Media Browser + + +
+
+

What's New +

+ +
+ + + +

My Library +

+ +
+ +

Collections +

+ +
+
+
+ + diff --git a/Html/itemDetails.html b/Html/itemDetails.html new file mode 100644 index 0000000000..6dac0a486e --- /dev/null +++ b/Html/itemDetails.html @@ -0,0 +1,66 @@ + + + + + + +
+
+ +

+ +
+
+
+
+ + +
+
+ +
+ +

+

+

+

+ +

+

+ +

+

+
+
+ +
+

Media Info

+
+
+
+

Scenes

+
+
+
+

Special Features

+

I'm the collapsible content. By default I'm closed, but you can click the header to open me.

+
+
+

Trailers

+

I'm the collapsible content. By default I'm closed, but you can click the header to open me.

+
+
+

Cast & Crew

+

I'm the collapsible content. By default I'm closed, but you can click the header to open me.

+
+
+

Gallery

+
+
+
+
+ + diff --git a/Html/library.html b/Html/library.html new file mode 100644 index 0000000000..9ba35b03ac --- /dev/null +++ b/Html/library.html @@ -0,0 +1,57 @@ + + + + + + +
+ +
+
+ +
+ +
+

Below are your media collections. Expand a collection to add or remove media locations assigned to it.

+

+ +

+
+
+
+
+
+ +
+ + diff --git a/Html/log.html b/Html/log.html new file mode 100644 index 0000000000..db76240ffa --- /dev/null +++ b/Html/log.html @@ -0,0 +1,30 @@ + + + + Log File + + +
+ +
+
+ +

+ + +

+ +

+ + +

+
+
+
+ + diff --git a/Html/login.html b/Html/login.html new file mode 100644 index 0000000000..4cb73c06ef --- /dev/null +++ b/Html/login.html @@ -0,0 +1,39 @@ + + + + Sign In + + +
+ +
+
+
+ + + + +
+ + diff --git a/Html/metadata.html b/Html/metadata.html new file mode 100644 index 0000000000..4618dd4bd8 --- /dev/null +++ b/Html/metadata.html @@ -0,0 +1,59 @@ + + + + Metadata + + +
+ +
+ +
+ + +
+
    +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
+
+
+ +
+ + +
+ + diff --git a/Html/metadataImages.html b/Html/metadataImages.html new file mode 100644 index 0000000000..5c9e7e02d2 --- /dev/null +++ b/Html/metadataImages.html @@ -0,0 +1,120 @@ + + + + Metadata + + +
+ +
+ +
+ + +
+
    +
  • + + +
    + When enabled, images will be refreshed periodically +
    +
  • +
  • + + +
  • +
  • + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
  • +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
+
+
+ +
+ + +
+ + diff --git a/Html/pluginCatalog.html b/Html/pluginCatalog.html new file mode 100644 index 0000000000..1b5ad74286 --- /dev/null +++ b/Html/pluginCatalog.html @@ -0,0 +1,22 @@ + + + + Plugins + + +
+ +
+ +
+
+ + diff --git a/Html/pluginUpdates.html b/Html/pluginUpdates.html new file mode 100644 index 0000000000..ed5ba54b11 --- /dev/null +++ b/Html/pluginUpdates.html @@ -0,0 +1,34 @@ + + + + Plugins + + +
+ +
+
+ + +
+ + + + + + + + + + +
Automatic updatesUpdate level
+
+
+
+
+ + diff --git a/Html/plugins.html b/Html/plugins.html new file mode 100644 index 0000000000..ee74ae3756 --- /dev/null +++ b/Html/plugins.html @@ -0,0 +1,24 @@ + + + + Plugins + + +
+ +
+ +
+
+ + diff --git a/Html/scheduledTask.html b/Html/scheduledTask.html new file mode 100644 index 0000000000..fbfe3cc715 --- /dev/null +++ b/Html/scheduledTask.html @@ -0,0 +1,90 @@ + + + + + + +
+
+
+
+

+

+ +

+
    +
    +
    +
    + +
    + + diff --git a/Html/scheduledTasks.html b/Html/scheduledTasks.html new file mode 100644 index 0000000000..dfbac291b5 --- /dev/null +++ b/Html/scheduledTasks.html @@ -0,0 +1,18 @@ + + + + Scheduled Tasks + + +
    +
    +
    +
    +

    Below are Media Browser's scheduled tasks. Click into a task to adjust it's schedule.

    +
      +
      +
      +
      +
      + + diff --git a/Html/scripts/AddPluginPage.js b/Html/scripts/AddPluginPage.js new file mode 100644 index 0000000000..e8cf82e869 --- /dev/null +++ b/Html/scripts/AddPluginPage.js @@ -0,0 +1,243 @@ +var AddPluginPage = { + + onPageShow: function () { + + var page = this; + + Dashboard.showLoadingMsg(); + + var name = getParameterByName('name'); + + var promise1 = ApiClient.getPackageInfo(name); + var promise2 = ApiClient.getInstalledPlugins(); + var promise3 = ApiClient.getPluginSecurityInfo(); + + $.when(promise1, promise2, promise3).done(function (response1, response2, response3) { + + AddPluginPage.renderPackage(response1[0], response2[0], response3[0], page); + + }); + }, + + renderPackage: function (pkg, installedPlugins, pluginSecurityInfo, page) { + + var installedPlugin = installedPlugins.filter(function (ip) { + return ip.Name == pkg.name; + })[0]; + + AddPluginPage.populateVersions(pkg, page, installedPlugin); + AddPluginPage.populateHistory(pkg); + + Dashboard.setPageTitle(pkg.name); + + if (pkg.shortDescription) { + $('#tagline', page).show().html(pkg.shortDescription); + } else { + $('#tagline', page).hide(); + } + + $('#overview', page).html(pkg.overview || ""); + + + $('#developer', page).html(pkg.owner); + + if (pkg.isPremium) { + $('.premiumPackage', page).show(); + + // Fill in registration info + var regStatus = ""; + if (pkg.isRegistered) { + regStatus += "You are currently registered for this feature"; + } else { + if (new Date(pkg.expDate).getTime() < new Date(1970, 1, 1).getTime()) { + regStatus += "You have never installed this feature"; + } else { + if (pkg.expDate <= new Date().getTime()) { + regStatus += "The trial period for this feature has expired on this machine"; + } else { + regStatus += "The trial period for this feature will expire in " + Math.round((new Date(pkg.expDate).getTime() - new Date().getTime()) / (86400000)) + " day(s)"; + } + } + } + + regStatus += ""; + $('#regStatus', page).html(regStatus); + + if (pluginSecurityInfo.IsMBSupporter) { + $('#regInfo', page).html(pkg.regInfo || ""); + // Fill in PayPal info + $('#featureId', page).val(pkg.featureId); + $('#featureName', page).val(pkg.name); + $('#amount', page).val(pkg.price); + $('#regPrice', page).html("

      Price: $" + pkg.price.toFixed(2) + " (USD)

      "); + var url = "http://mb3admin.com/admin/service/user/getPayPalEmail?id=" + pkg.owner; + $.getJSON(url).done(function (dev) { + if (dev.payPalEmail) { + $('#payPalEmail', page).val(dev.payPalEmail); + + } else { + $('#ppButton', page).hide(); + $('#noEmail', page).show(); + } + }); + } else { + $('#regInfo', page).html("

      You must be a Media Browser Supporter in order to register this feature.

      "); + $('#ppButton', page).hide(); + } + + } else { + $('.premiumPackage', page).hide(); + } + + if (pkg.richDescUrl) { + $('#pViewWebsite', page).show(); + $('#pViewWebsite a', page)[0].href = pkg.richDescUrl; + } else { + $('#pViewWebsite', page).hide(); + } + + if (pkg.previewImage) { + + var color = pkg.tileColor || "#2572EB"; + var img = pkg.previewImage ? pkg.previewImage : pkg.thumbImage; + $('#pPreviewImage', page).show().html(""); + } else { + $('#pPreviewImage', page).hide().html(""); + } + + if (installedPlugin) { + $('#pCurrentVersion', page).show().html("You currently have version " + installedPlugin.Version + " installed."); + + } else { + $('#pCurrentVersion', page).hide().html(""); + } + + Dashboard.hideLoadingMsg(); + }, + + populateVersions: function (packageInfo, page, installedPlugin) { + + var html = ''; + + for (var i = 0, length = packageInfo.versions.length; i < length; i++) { + + var version = packageInfo.versions[i]; + + html += ''; + + } + + var selectmenu = $('#selectVersion', page).html(html); + + var packageVersion; + + if (installedPlugin) { + + // Select the first available package with the same update class as the installed version + packageVersion = packageInfo.versions.filter(function (current) { + + return current.classification == installedPlugin.UpdateClass; + })[0]; + + + } else { + $('#pCurrentVersion', page).hide().html(""); + } + + // If we don't have a package version to select, pick the first release build + if (!packageVersion) { + + // Select the first available package with the same update class as the installed version + packageVersion = packageInfo.versions.filter(function (current) { + + return current.classification == "Release"; + })[0]; + } + + // If we still don't have a package version to select, pick the first Beta build + if (!packageVersion) { + + // Select the first available package with the same update class as the installed version + packageVersion = packageInfo.versions.filter(function (current) { + + return current.classification == "Beta"; + })[0]; + } + + if (packageVersion) { + var val = packageVersion.versionStr + '|' + packageVersion.classification; + + $('#selectVersion', page).val(val); + } + + selectmenu.selectmenu('refresh'); + }, + + populateHistory: function (packageInfo) { + + var html = ''; + + for (var i = 0, length = Math.min(packageInfo.versions.length, 10) ; i < length; i++) { + + var version = packageInfo.versions[i]; + + html += '

      ' + version.versionStr + ' (' + version.classification + ')

      '; + + html += '
      ' + version.description + '
      '; + } + + $('#revisionHistory', $.mobile.activePage).html(html); + }, + + onSubmit: function () { + + Dashboard.showLoadingMsg(); + + $('#btnInstall', $.mobile.activePage).button('disable'); + + var name = getParameterByName('name'); + + ApiClient.getInstalledPlugins().done(function (plugins) { + + var installedPlugin = plugins.filter(function (ip) { + return ip.Name == name; + })[0]; + + var vals = $('#selectVersion', $.mobile.activePage).val().split('|'); + + var version = vals[0]; + + if (installedPlugin && installedPlugin.Version == version) { + + Dashboard.hideLoadingMsg(); + + Dashboard.confirm("Are you sure you wish to reinstall the same version you already have? In most cases this will not have any effect.", "Plugin Reinstallation", function (confirmResult) { + + if (confirmResult) { + + Dashboard.showLoadingMsg(); + AddPluginPage.performInstallation(name, vals[1], version); + } else { + $('#btnInstall', $.mobile.activePage).button('enable'); + } + + }); + } else { + AddPluginPage.performInstallation(name, vals[1], version); + } + }); + + + return false; + }, + + performInstallation: function (packageName, updateClass, version) { + + ApiClient.installPlugin(packageName, updateClass, version).done(function () { + + Dashboard.hideLoadingMsg(); + }); + } +}; + +$(document).on('pageshow', "#addPluginPage", AddPluginPage.onPageShow); \ No newline at end of file diff --git a/Html/scripts/AdvancedConfigurationPage.js b/Html/scripts/AdvancedConfigurationPage.js new file mode 100644 index 0000000000..5c6f282fb0 --- /dev/null +++ b/Html/scripts/AdvancedConfigurationPage.js @@ -0,0 +1,63 @@ +var AdvancedConfigurationPage = { + + onPageShow: function () { + Dashboard.showLoadingMsg(); + + var promise1 = ApiClient.getServerConfiguration(); + + var promise2 = ApiClient.getSystemInfo(); + + $.when(promise1, promise2).done(function (response1, response2) { + + AdvancedConfigurationPage.loadPage(response1[0], response2[0]); + + }); + }, + + loadPage: function (config, systemInfo) { + + var page = $.mobile.activePage; + + if (systemInfo.SupportsNativeWebSocket) { + + $('#fldWebSocketPortNumber', page).hide(); + } else { + $('#fldWebSocketPortNumber', page).show(); + } + + $('#txtWebSocketPortNumber', page).val(config.LegacyWebSocketPortNumber); + + $('#txtPortNumber', page).val(config.HttpServerPortNumber); + $('#chkDebugLog', page).checked(config.EnableDebugLevelLogging).checkboxradio("refresh"); + + $('#chkEnableDeveloperTools', page).checked(config.EnableDeveloperTools).checkboxradio("refresh"); + $('#chkRunAtStartup', page).checked(config.RunAtStartup).checkboxradio("refresh"); + + Dashboard.hideLoadingMsg(); + }, + + onSubmit: function () { + + Dashboard.showLoadingMsg(); + + var form = this; + + ApiClient.getServerConfiguration().done(function (config) { + + config.LegacyWebSocketPortNumber = $('#txtWebSocketPortNumber', form).val(); + + config.HttpServerPortNumber = $('#txtPortNumber', form).val(); + config.EnableDebugLevelLogging = $('#chkDebugLog', form).checked(); + + config.EnableDeveloperTools = $('#chkEnableDeveloperTools', form).checked(); + config.RunAtStartup = $('#chkRunAtStartup', form).checked(); + + ApiClient.updateServerConfiguration(config).done(Dashboard.processServerConfigurationUpdateResult); + }); + + // Disable default form submission + return false; + } +}; + +$(document).on('pageshow', "#advancedConfigurationPage", AdvancedConfigurationPage.onPageShow); diff --git a/Html/scripts/AdvancedMetadataConfigurationPage.js b/Html/scripts/AdvancedMetadataConfigurationPage.js new file mode 100644 index 0000000000..73ed3f4311 --- /dev/null +++ b/Html/scripts/AdvancedMetadataConfigurationPage.js @@ -0,0 +1,65 @@ +var AdvancedMetadataConfigurationPage = { + + onPageShow: function () { + + Dashboard.showLoadingMsg(); + + var page = this; + + var promise1 = ApiClient.getServerConfiguration(); + var promise2 = ApiClient.getItemTypes({ HasInternetProvider: true }); + + $.when(promise1, promise2).done(function (response1, response2) { + + AdvancedMetadataConfigurationPage.load(page, response1[0], response2[0]); + + }); + }, + + load: function (page, config, itemTypes) { + + AdvancedMetadataConfigurationPage.loadItemTypes(page, config, itemTypes); + Dashboard.hideLoadingMsg(); + }, + + loadItemTypes: function (page, configuration, types) { + + var html = '
      '; + + for (var i = 0, length = types.length; i < length; i++) { + + var type = types[i]; + var id = "checkbox-" + i + "a"; + + var checkedAttribute = configuration.InternetProviderExcludeTypes.indexOf(type) != -1 ? ' checked="checked"' : ''; + + html += ''; + html += ''; + } + + html += "
      "; + + $('#divItemTypes', page).html(html).trigger("create"); + }, + + onSubmit: function () { + Dashboard.showLoadingMsg(); + + var form = this; + + ApiClient.getServerConfiguration().done(function (config) { + + config.InternetProviderExcludeTypes = $.map($('.chkItemType:checked', form), function (currentCheckbox) { + + return currentCheckbox.getAttribute('data-itemtype'); + }); + + ApiClient.updateServerConfiguration(config).done(Dashboard.processServerConfigurationUpdateResult); + }); + + // Disable default form submission + return false; + } +}; + +$(document).on('pageshow', "#advancedMetadataConfigurationPage", AdvancedMetadataConfigurationPage.onPageShow); \ No newline at end of file diff --git a/Html/scripts/DashboardPage.js b/Html/scripts/DashboardPage.js new file mode 100644 index 0000000000..93163de79d --- /dev/null +++ b/Html/scripts/DashboardPage.js @@ -0,0 +1,423 @@ +var DashboardPage = { + + onPageShow: function () { + + Dashboard.showLoadingMsg(); + DashboardPage.pollForInfo(); + DashboardPage.startInterval(); + $(document).on("websocketmessage", DashboardPage.onWebSocketMessage).on("websocketopen", DashboardPage.onWebSocketConnectionChange).on("websocketerror", DashboardPage.onWebSocketConnectionChange).on("websocketclose", DashboardPage.onWebSocketConnectionChange); + + DashboardPage.lastAppUpdateCheck = null; + DashboardPage.lastPluginUpdateCheck = null; + }, + + onPageHide: function () { + + $(document).off("websocketmessage", DashboardPage.onWebSocketMessage).off("websocketopen", DashboardPage.onWebSocketConnectionChange).off("websocketerror", DashboardPage.onWebSocketConnectionChange).off("websocketclose", DashboardPage.onWebSocketConnectionChange); + DashboardPage.stopInterval(); + }, + + startInterval: function () { + + if (Dashboard.isWebSocketOpen()) { + Dashboard.sendWebSocketMessage("DashboardInfoStart", "0,1500"); + } + }, + + stopInterval: function () { + + if (Dashboard.isWebSocketOpen()) { + Dashboard.sendWebSocketMessage("DashboardInfoStop"); + } + }, + + onWebSocketMessage: function (e, msg) { + + if (msg.MessageType == "DashboardInfo") { + DashboardPage.renderInfo(msg.Data); + } + }, + + onWebSocketConnectionChange: function () { + + DashboardPage.stopInterval(); + DashboardPage.startInterval(); + }, + + pollForInfo: function () { + $.getJSON("dashboardInfo").done(DashboardPage.renderInfo); + }, + + renderInfo: function (dashboardInfo) { + + DashboardPage.lastDashboardInfo = dashboardInfo; + + DashboardPage.renderRunningTasks(dashboardInfo); + DashboardPage.renderSystemInfo(dashboardInfo); + DashboardPage.renderActiveConnections(dashboardInfo); + + Dashboard.hideLoadingMsg(); + }, + + renderActiveConnections: function (dashboardInfo) { + + var page = $.mobile.activePage; + + var html = ''; + + if (!dashboardInfo.ActiveConnections.length) { + html += '

      There are no users currently connected.

      '; + $('#divConnections', page).html(html).trigger('create'); + return; + } + + html += ''; + + for (var i = 0, length = dashboardInfo.ActiveConnections.length; i < length; i++) { + + var connection = dashboardInfo.ActiveConnections[i]; + + var user = dashboardInfo.Users.filter(function (u) { + return u.Id == connection.UserId; + })[0]; + + html += ''; + + html += ''; + + html += ''; + + html += ''; + + html += ''; + + html += ''; + + html += ''; + + } + + html += '
      '; + html += DashboardPage.getClientType(connection); + html += ''; + html += user.Name; + html += ''; + html += connection.DeviceName; + html += ''; + html += DashboardPage.getNowPlayingImage(connection.NowPlayingItem); + html += ''; + html += DashboardPage.getNowPlayingText(connection, connection.NowPlayingItem); + html += '
      '; + + $('#divConnections', page).html(html); + }, + + getClientType: function (connection) { + + if (connection.ClientType == "Dashboard") { + + return "Dashboard"; + } + if (connection.ClientType == "Pc") { + + return "Media Browser"; + } + if (connection.ClientType == "Android") { + + return "Android"; + } + if (connection.ClientType == "Ios") { + + return "iOS"; + } + if (connection.ClientType == "WindowsRT") { + + return "Windows RT"; + } + if (connection.ClientType == "WindowsPhone") { + + return "Windows Phone"; + } + + return connection.ClientType; + }, + + getNowPlayingImage: function (item) { + + if (item) { + + if (item.BackdropImageTag) { + var url = ApiClient.getImageUrl(item.Id, { + type: "Backdrop", + height: 100, + tag: item.BackdropImageTag + }); + + return "" + item.Name + ""; + } + else if (item.PrimaryImageTag) { + + var url = ApiClient.getImageUrl(item.Id, { + type: "Primary", + height: 100, + tag: item.PrimaryImageTag + }); + + return "" + item.Name + ""; + } + } + + return ""; + }, + + getNowPlayingText: function (connection, item) { + + var html = ""; + + if (item) { + + html += "
      " + item.Name + "
      "; + + html += "
      "; + + if (item.RunTimeTicks) { + html += DashboardPage.getDisplayText(connection.NowPlayingPositionTicks || 0) + " / "; + + html += DashboardPage.getDisplayText(item.RunTimeTicks); + } + + html += "
      "; + } + + return html; + }, + + getDisplayText: function (ticks) { + + var ticksPerHour = 36000000000; + + var parts = []; + + var hours = ticks / ticksPerHour; + hours = parseInt(hours); + + if (hours) { + parts.push(hours); + } + + ticks -= (hours * ticksPerHour); + + var ticksPerMinute = 600000000; + + var minutes = ticks / ticksPerMinute; + minutes = parseInt(minutes); + + ticks -= (minutes * ticksPerMinute); + + if (minutes < 10) { + minutes = '0' + minutes; + } + parts.push(minutes); + + var ticksPerSecond = 10000000; + + var seconds = ticks / ticksPerSecond; + seconds = parseInt(seconds); + + if (seconds < 10) { + seconds = '0' + seconds; + } + parts.push(seconds); + + return parts.join(':'); + }, + + renderRunningTasks: function (dashboardInfo) { + + var page = $.mobile.activePage; + + var html = ''; + + if (!dashboardInfo.RunningTasks.length) { + html += '

      No tasks are currently running.

      '; + } + + for (var i = 0, length = dashboardInfo.RunningTasks.length; i < length; i++) { + + + var task = dashboardInfo.RunningTasks[i]; + + html += '

      '; + + html += task.Name; + + if (task.State == "Running") { + var progress = task.CurrentProgress || { PercentComplete: 0 }; + html += ' - ' + Math.round(progress.PercentComplete) + '%'; + + html += ''; + } + else if (task.State == "Cancelling") { + html += ' - Stopping'; + } + + html += '

      '; + } + + + $('#divRunningTasks', page).html(html).trigger('create'); + }, + + renderSystemInfo: function (dashboardInfo) { + + Dashboard.updateSystemInfo(dashboardInfo.SystemInfo); + + var page = $.mobile.activePage; + + $('#appVersionNumber', page).html(dashboardInfo.SystemInfo.Version); + + if (dashboardInfo.RunningTasks.filter(function (task) { + + return task.Id == dashboardInfo.ApplicationUpdateTaskId; + + }).length) { + + $('#btnUpdateApplication', page).button('disable'); + } else { + $('#btnUpdateApplication', page).button('enable'); + } + + DashboardPage.renderApplicationUpdateInfo(dashboardInfo); + DashboardPage.renderPluginUpdateInfo(dashboardInfo); + }, + + renderApplicationUpdateInfo: function (dashboardInfo) { + + var page = $.mobile.activePage; + + if (dashboardInfo.SystemInfo.IsNetworkDeployed && !dashboardInfo.SystemInfo.HasPendingRestart) { + + // Only check once every 10 mins + if (DashboardPage.lastAppUpdateCheck && (new Date().getTime() - DashboardPage.lastAppUpdateCheck) < 600000) { + return; + } + + DashboardPage.lastAppUpdateCheck = new Date().getTime(); + + ApiClient.getAvailableApplicationUpdate().done(function (packageInfo) { + + var version = packageInfo.versions[0]; + + if (!version) { + $('#pUpToDate', page).show(); + $('#pUpdateNow', page).hide(); + } else { + $('#pUpToDate', page).hide(); + + $('#pUpdateNow', page).show(); + + $('#newVersionNumber', page).html("Version " + version.versionStr + " is now available for download."); + } + + }).fail(function () { + + Dashboard.showFooterNotification({ html: 'There was an error connecting to the remote Media Browser repository.', id: "MB3ConnectionError" }); + + }); + + } else { + + if (dashboardInfo.SystemInfo.HasPendingRestart) { + $('#pUpToDate', page).hide(); + } else { + $('#pUpToDate', page).show(); + } + + $('#pUpdateNow', page).hide(); + } + }, + + renderPluginUpdateInfo: function (dashboardInfo) { + + // Only check once every 10 mins + if (DashboardPage.lastPluginUpdateCheck && (new Date().getTime() - DashboardPage.lastPluginUpdateCheck) < 600000) { + return; + } + + DashboardPage.lastPluginUpdateCheck = new Date().getTime(); + + var page = $.mobile.activePage; + + ApiClient.getAvailablePluginUpdates().done(function (updates) { + + if (updates.length) { + + $('#collapsiblePluginUpdates', page).show(); + + } else { + $('#collapsiblePluginUpdates', page).hide(); + + return; + } + var html = ''; + + for (var i = 0, length = updates.length; i < length; i++) { + + var update = updates[i]; + + html += '

      A new version of ' + update.name + ' is available!

      '; + + html += ''; + } + + $('#pPluginUpdates', page).html(html).trigger('create'); + + }).fail(function () { + + Dashboard.showFooterNotification({ html: 'There was an error connecting to the remote Media Browser repository.', id: "MB3ConnectionError" }); + + }); + }, + + installPluginUpdate: function (button) { + + $(button).button('disable'); + + var name = button.getAttribute('data-name'); + var version = button.getAttribute('data-version'); + var classification = button.getAttribute('data-classification'); + + Dashboard.showLoadingMsg(); + + ApiClient.installPlugin(name, classification, version).done(function () { + + Dashboard.hideLoadingMsg(); + }); + }, + + updateApplication: function () { + + var page = $.mobile.activePage; + $('#btnUpdateApplication', page).button('disable'); + + Dashboard.showLoadingMsg(); + + ApiClient.startScheduledTask(DashboardPage.lastDashboardInfo.ApplicationUpdateTaskId).done(function () { + + DashboardPage.pollForInfo(); + + Dashboard.hideLoadingMsg(); + }); + }, + + stopTask: function (id) { + + ApiClient.stopScheduledTask(id).done(function () { + + DashboardPage.pollForInfo(); + }); + + } +}; + +$(document).on('pageshow', "#dashboardPage", DashboardPage.onPageShow).on('pagehide', "#dashboardPage", DashboardPage.onPageHide); \ No newline at end of file diff --git a/Html/scripts/DisplaySettingsPage.js b/Html/scripts/DisplaySettingsPage.js new file mode 100644 index 0000000000..da87a106f7 --- /dev/null +++ b/Html/scripts/DisplaySettingsPage.js @@ -0,0 +1,46 @@ +var DisplaySettingsPage = { + + onPageShow: function () { + Dashboard.showLoadingMsg(); + + var page = this; + + ApiClient.getServerConfiguration().done(function (config) { + + $('#txtWeatherLocation', page).val(config.WeatherLocation); + $('#txtMinResumePct', page).val(config.MinResumePct); + $('#txtMaxResumePct', page).val(config.MaxResumePct); + $('#txtMinResumeDuration', page).val(config.MinResumeDurationSeconds); + $('#selectWeatherUnit', page).val(config.WeatherUnit).selectmenu("refresh"); + + Dashboard.hideLoadingMsg(); + }); + + }, + + submit: function() { + + $('.btnSubmit', $.mobile.activePage)[0].click(); + + }, + + onSubmit: function () { + var form = this; + + ApiClient.getServerConfiguration().done(function (config) { + + config.WeatherLocation = $('#txtWeatherLocation', form).val(); + config.WeatherUnit = $('#selectWeatherUnit', form).val(); + config.MinResumePct = $('#txtMinResumePct', form).val(); + config.MaxResumePct = $('#txtMaxResumePct', form).val(); + config.MinResumeDurationSeconds = $('#txtMinResumeDuration', form).val(); + + ApiClient.updateServerConfiguration(config); + }); + + // Disable default form submission + return false; + } +}; + +$(document).on('pageshow', "#displaySettingsPage", DisplaySettingsPage.onPageShow); diff --git a/Html/scripts/EditUserPage.js b/Html/scripts/EditUserPage.js new file mode 100644 index 0000000000..0d362e5dea --- /dev/null +++ b/Html/scripts/EditUserPage.js @@ -0,0 +1,175 @@ +var EditUserPage = { + + onPageShow: function () { + Dashboard.showLoadingMsg(); + + var userId = getParameterByName("userId"); + + if (userId) { + $('#userProfileNavigation', this).show(); + } else { + $('#userProfileNavigation', this).hide(); + } + + var promise4 = ApiClient.getCultures(); + + var promise3 = ApiClient.getParentalRatings(); + + var promise1; + + if (!userId) { + + var deferred = $.Deferred(); + + deferred.resolveWith(null, [{ + Configuration: {} + }]); + + promise1 = deferred.promise(); + } else { + + promise1 = ApiClient.getUser(userId); + } + + var promise2 = Dashboard.getCurrentUser(); + + $.when(promise1, promise2, promise3, promise4).done(function (response1, response2, response3, response4) { + + EditUserPage.loadUser(response1[0] || response1, response2[0], response3[0], response4[0]); + + }); + }, + + loadUser: function (user, loggedInUser, allParentalRatings, allCultures) { + + var page = $($.mobile.activePage); + + EditUserPage.populateLanguages($('#selectAudioLanguage', page), allCultures); + EditUserPage.populateLanguages($('#selectSubtitleLanguage', page), allCultures); + EditUserPage.populateRatings(allParentalRatings, page); + + if (!loggedInUser.Configuration.IsAdministrator || user.Id == loggedInUser.Id) { + + $('#fldIsAdmin', page).hide(); + $('#fldMaxParentalRating', page).hide(); + } else { + $('#fldIsAdmin', page).show(); + $('#fldMaxParentalRating', page).show(); + } + + Dashboard.setPageTitle(user.Name || "Add User"); + + $('#txtUserName', page).val(user.Name); + + var ratingValue = ""; + + if (user.Configuration.MaxParentalRating) { + + for (var i = 0, length = allParentalRatings.length; i < length; i++) { + + var rating = allParentalRatings[i]; + + if (user.Configuration.MaxParentalRating >= rating.Value) { + ratingValue = rating.Value; + } + } + } + + $('#selectMaxParentalRating', page).val(ratingValue).selectmenu("refresh"); + + $('#selectAudioLanguage', page).val(user.Configuration.AudioLanguagePreference || "").selectmenu("refresh"); + $('#selectSubtitleLanguage', page).val(user.Configuration.SubtitleLanguagePreference || "").selectmenu("refresh"); + + $('#chkForcedSubtitlesOnly', page).checked(user.Configuration.UseForcedSubtitlesOnly || false).checkboxradio("refresh"); + $('#chkIsAdmin', page).checked(user.Configuration.IsAdministrator || false).checkboxradio("refresh"); + + Dashboard.hideLoadingMsg(); + }, + + populateLanguages: function (select, allCultures) { + + var html = ""; + + html += ""; + + for (var i = 0, length = allCultures.length; i < length; i++) { + + var culture = allCultures[i]; + + html += ""; + } + + select.html(html).selectmenu("refresh"); + }, + + populateRatings: function (allParentalRatings, page) { + + var html = ""; + + html += ""; + + for (var i = 0, length = allParentalRatings.length; i < length; i++) { + + var rating = allParentalRatings[i]; + + html += ""; + } + + $('#selectMaxParentalRating', page).html(html).selectmenu("refresh"); + }, + + saveUser: function (user) { + + var page = $($.mobile.activePage); + + user.Name = $('#txtUserName', page).val(); + user.Configuration.MaxParentalRating = $('#selectMaxParentalRating', page).val() || null; + + user.Configuration.IsAdministrator = $('#chkIsAdmin', page).checked(); + + user.Configuration.AudioLanguagePreference = $('#selectAudioLanguage', page).val(); + user.Configuration.SubtitleLanguagePreference = $('#selectSubtitleLanguage', page).val(); + user.Configuration.UseForcedSubtitlesOnly = $('#chkForcedSubtitlesOnly', page).checked(); + + var userId = getParameterByName("userId"); + + if (userId) { + ApiClient.updateUser(user).done(EditUserPage.saveComplete); + } else { + ApiClient.createUser(user).done(EditUserPage.saveComplete); + } + }, + + saveComplete: function () { + Dashboard.hideLoadingMsg(); + + var userId = getParameterByName("userId"); + + Dashboard.validateCurrentUser(); + + if (userId) { + Dashboard.alert("Settings saved."); + } else { + Dashboard.navigate("userProfiles.html"); + } + }, + + onSubmit: function () { + Dashboard.showLoadingMsg(); + + var userId = getParameterByName("userId"); + + if (!userId) { + EditUserPage.saveUser({ + Configuration: {} + }); + } else { + ApiClient.getUser(userId).done(EditUserPage.saveUser); + } + + // Disable default form submission + return false; + } +}; + +$(document).on('pageshow', "#editUserPage", EditUserPage.onPageShow); diff --git a/Html/scripts/Extensions.js b/Html/scripts/Extensions.js new file mode 100644 index 0000000000..dba43a7046 --- /dev/null +++ b/Html/scripts/Extensions.js @@ -0,0 +1,333 @@ +// Array Remove - By John Resig (MIT Licensed) +Array.prototype.remove = function (from, to) { + var rest = this.slice((to || from) + 1 || this.length); + this.length = from < 0 ? this.length + from : from; + return this.push.apply(this, rest); +}; + +String.prototype.endsWith = function (suffix) { + return this.indexOf(suffix, this.length - suffix.length) !== -1; +}; + +$.fn.checked = function (value) { + if (value === true || value === false) { + // Set the value of the checkbox + return $(this).each(function () { + this.checked = value; + }); + } else { + // Return check state + return $(this).is(':checked'); + } +}; + +var WebNotifications = { + + show: function (data) { + if (window.webkitNotifications) { + if (!webkitNotifications.checkPermission()) { + var notif = webkitNotifications.createNotification(data.icon, data.title, data.body); + notif.show(); + + if (data.timeout) { + setTimeout(function () { + notif.cancel(); + }, data.timeout); + } + + return notif; + } else { + webkitNotifications.requestPermission(function () { + return WebNotifications.show(data); + }); + } + } + else if (window.Notification) { + if (Notification.permissionLevel() === "granted") { + var notif = new Notification(data.title, data); + notif.show(); + + if (data.timeout) { + setTimeout(function () { + notif.cancel(); + }, data.timeout); + } + + return notif; + } else if (Notification.permissionLevel() === "default") { + Notification.requestPermission(function () { + return WebNotifications.show(data); + }); + } + } + }, + + requestPermission: function () { + if (window.webkitNotifications) { + if (!webkitNotifications.checkPermission()) { + } else { + webkitNotifications.requestPermission(function () { + }); + } + } + else if (window.Notification) { + if (Notification.permissionLevel() === "granted") { + } else if (Notification.permissionLevel() === "default") { + Notification.requestPermission(function () { + }); + } + } + } +}; + +/* + * Javascript Humane Dates + * Copyright (c) 2008 Dean Landolt (deanlandolt.com) + * Re-write by Zach Leatherman (zachleat.com) + * + * Adopted from the John Resig's pretty.js + * at http://ejohn.org/blog/javascript-pretty-date + * and henrah's proposed modification + * at http://ejohn.org/blog/javascript-pretty-date/#comment-297458 + * + * Licensed under the MIT license. + */ + +function humane_date(date_str) { + var time_formats = [[90, 'a minute'], // 60*1.5 + [3600, 'minutes', 60], // 60*60, 60 + [5400, 'an hour'], // 60*60*1.5 + [86400, 'hours', 3600], // 60*60*24, 60*60 + [129600, 'a day'], // 60*60*24*1.5 + [604800, 'days', 86400], // 60*60*24*7, 60*60*24 + [907200, 'a week'], // 60*60*24*7*1.5 + [2628000, 'weeks', 604800], // 60*60*24*(365/12), 60*60*24*7 + [3942000, 'a month'], // 60*60*24*(365/12)*1.5 + [31536000, 'months', 2628000], // 60*60*24*365, 60*60*24*(365/12) + [47304000, 'a year'], // 60*60*24*365*1.5 + [3153600000, 'years', 31536000] // 60*60*24*365*100, 60*60*24*365 + ]; + + var dt = new Date; + var date = parseISO8601Date(date_str, true); + + var seconds = ((dt - date) / 1000); + var token = ' ago'; + var i = 0; + var format; + + if (seconds < 0) { + seconds = Math.abs(seconds); + token = ''; + } + + while (format = time_formats[i++]) { + if (seconds < format[0]) { + if (format.length == 2) { + return format[1] + token; + } else { + return Math.round(seconds / format[2]) + ' ' + format[1] + token; + } + } + } + + // overflow for centuries + if (seconds > 4730400000) + return Math.round(seconds / 4730400000) + ' centuries' + token; + + return date_str; +}; + +function humane_elapsed(firstDateStr, secondDateStr) { + var dt1 = new Date(firstDateStr); + var dt2 = new Date(secondDateStr); + var seconds = (dt2.getTime() - dt1.getTime()) / 1000; + var numdays = Math.floor((seconds % 31536000) / 86400); + var numhours = Math.floor(((seconds % 31536000) % 86400) / 3600); + var numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60); + var numseconds = Math.round((((seconds % 31536000) % 86400) % 3600) % 60); + + var elapsedStr = ''; + elapsedStr += numdays == 1 ? numdays + ' day ' : ''; + elapsedStr += numdays > 1 ? numdays + ' days ' : ''; + elapsedStr += numhours == 1 ? numhours + ' hour ' : ''; + elapsedStr += numhours > 1 ? numhours + ' hours ' : ''; + elapsedStr += numminutes == 1 ? numminutes + ' minute ' : ''; + elapsedStr += numminutes > 1 ? numminutes + ' minutes ' : ''; + elapsedStr += elapsedStr.length > 0 ? 'and ' : ''; + elapsedStr += numseconds == 1 ? numseconds + ' second' : ''; + elapsedStr += numseconds == 0 || numseconds > 1 ? numseconds + ' seconds' : ''; + + return elapsedStr; + +} + +function getParameterByName(name) { + name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]"); + var regexS = "[\\?&]" + name + "=([^&#]*)"; + var regex = new RegExp(regexS); + var results = regex.exec(window.location.search); + if (results == null) + return ""; + else + return decodeURIComponent(results[1].replace(/\+/g, " ")); +} + +function parseISO8601Date(s, toLocal) { + + // parenthese matches: + // year month day hours minutes seconds + // dotmilliseconds + // tzstring plusminus hours minutes + var re = /(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(\.\d+)?(Z|([+-])(\d\d):(\d\d))/; + + var d = []; + d = s.match(re); + + // "2010-12-07T11:00:00.000-09:00" parses to: + // ["2010-12-07T11:00:00.000-09:00", "2010", "12", "07", "11", + // "00", "00", ".000", "-09:00", "-", "09", "00"] + // "2010-12-07T11:00:00.000Z" parses to: + // ["2010-12-07T11:00:00.000Z", "2010", "12", "07", "11", + // "00", "00", ".000", "Z", undefined, undefined, undefined] + + if (!d) { + throw "Couldn't parse ISO 8601 date string '" + s + "'"; + } + + // parse strings, leading zeros into proper ints + var a = [1, 2, 3, 4, 5, 6, 10, 11]; + for (var i in a) { + d[a[i]] = parseInt(d[a[i]], 10); + } + d[7] = parseFloat(d[7]); + + // Date.UTC(year, month[, date[, hrs[, min[, sec[, ms]]]]]) + // note that month is 0-11, not 1-12 + // see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/UTC + var ms = Date.UTC(d[1], d[2] - 1, d[3], d[4], d[5], d[6]); + + // if there are milliseconds, add them + if (d[7] > 0) { + ms += Math.round(d[7] * 1000); + } + + // if there's a timezone, calculate it + if (d[8] != "Z" && d[10]) { + var offset = d[10] * 60 * 60 * 1000; + if (d[11]) { + offset += d[11] * 60 * 1000; + } + if (d[9] == "-") { + ms -= offset; + } else { + ms += offset; + } + } else if (!toLocal) { + ms += new Date().getTimezoneOffset() * 60000; + } + + return new Date(ms); +}; + + + +// jqm.page.params.js - version 0.1 +// Copyright (c) 2011, Kin Blas +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(function ($, window, undefined) { + + // Given a query string, convert all the name/value pairs + // into a property/value object. If a name appears more than + // once in a query string, the value is automatically turned + // into an array. + function queryStringToObject(qstr) { + var result = {}, nvPairs = ((qstr || "").replace(/^\?/, "").split(/&/)), i, pair, n, v; + + for (i = 0; i < nvPairs.length; i++) { + var pstr = nvPairs[i]; + if (pstr) { + pair = pstr.split(/=/); + n = pair[0]; + v = pair[1]; + if (result[n] === undefined) { + result[n] = v; + } else { + if (typeof result[n] !== "object") { + result[n] = [result[n]]; + } + result[n].push(v); + } + } + } + + return result; + } + + // The idea here is to listen for any pagebeforechange notifications from + // jQuery Mobile, and then muck with the toPage and options so that query + // params can be passed to embedded/internal pages. So for example, if a + // changePage() request for a URL like: + // + // http://mycompany.com/myapp/#page-1?foo=1&bar=2 + // + // is made, the page that will actually get shown is: + // + // http://mycompany.com/myapp/#page-1 + // + // The browser's location will still be updated to show the original URL. + // The query params for the embedded page are also added as a property/value + // object on the options object. You can access it from your page notifications + // via data.options.pageData. + $(document).bind("pagebeforechange", function (e, data) { + + // We only want to handle the case where we are being asked + // to go to a page by URL, and only if that URL is referring + // to an internal page by id. + + if (typeof data.toPage === "string") { + var u = $.mobile.path.parseUrl(data.toPage); + if ($.mobile.path.isEmbeddedPage(u)) { + + // The request is for an internal page, if the hash + // contains query (search) params, strip them off the + // toPage URL and then set options.dataUrl appropriately + // so the location.hash shows the originally requested URL + // that hash the query params in the hash. + + var u2 = $.mobile.path.parseUrl(u.hash.replace(/^#/, "")); + if (u2.search) { + if (!data.options.dataUrl) { + data.options.dataUrl = data.toPage; + } + data.options.pageData = queryStringToObject(u2.search); + data.toPage = u.hrefNoHash + "#" + u2.pathname; + } + } + } + }); + +})(jQuery, window); \ No newline at end of file diff --git a/Html/scripts/IndexPage.js b/Html/scripts/IndexPage.js new file mode 100644 index 0000000000..ee84e07de9 --- /dev/null +++ b/Html/scripts/IndexPage.js @@ -0,0 +1,106 @@ +var IndexPage = { + + onPageShow: function () { + IndexPage.loadLibrary(Dashboard.getCurrentUserId(), this); + }, + + loadLibrary: function (userId, page) { + + if (!userId) { + return; + } + + page = $(page); + + var options = { + + limit: 5, + sortBy: "DateCreated", + sortOrder: "Descending", + filters: "IsRecentlyAdded,IsNotFolder", + ImageTypes: "Primary,Backdrop,Thumb", + recursive: true + }; + + ApiClient.getItems(userId, options).done(function (result) { + + $('#divWhatsNew', page).html(Dashboard.getPosterViewHtml({ + items: result.Items, + preferBackdrop: true, + showTitle: true + })); + + }); + + options = { + + limit: 5, + sortBy: "DatePlayed", + sortOrder: "Descending", + filters: "IsResumable", + recursive: true + }; + + ApiClient.getItems(userId, options).done(function (result) { + + $('#divResumableItems', page).html(Dashboard.getPosterViewHtml({ + items: result.Items, + preferBackdrop: true, + showTitle: true + })); + + if (result.Items.length) { + $('#divResumable', page).show(); + } else { + $('#divResumable', page).hide(); + } + + }); + + options = { + + sortBy: "SortName" + }; + + ApiClient.getItems(userId, options).done(function (result) { + + $('#divCollections', page).html(Dashboard.getPosterViewHtml({ + items: result.Items, + showTitle: true + })); + + }); + + IndexPage.loadMyLibrary(userId, page); + }, + + loadMyLibrary: function (userId, page) { + + var items = [{ + Name: "Recently Played", + IsFolder: true + }, { + Name: "Favorites", + IsFolder: true + }, { + Name: "Genres", + IsFolder: true + }, { + Name: "Studios", + IsFolder: true + }, { + Name: "Performers", + IsFolder: true + }, { + Name: "Directors", + IsFolder: true + }]; + + $('#divMyLibrary', page).html(Dashboard.getPosterViewHtml({ + items: items, + showTitle: true + })); + } +}; + +$(document).on('pageshow', "#indexPage", IndexPage.onPageShow); \ No newline at end of file diff --git a/Html/scripts/ItemDetailPage.js b/Html/scripts/ItemDetailPage.js new file mode 100644 index 0000000000..e5629f217f --- /dev/null +++ b/Html/scripts/ItemDetailPage.js @@ -0,0 +1,353 @@ +var ItemDetailPage = { + + onPageShow: function () { + + var id = getParameterByName('id'); + + Dashboard.showLoadingMsg(); + + ApiClient.getItem(Dashboard.getCurrentUserId(), id).done(ItemDetailPage.renderItem); + + }, + + renderItem: function (item) { + + var page = $.mobile.activePage; + + ItemDetailPage.item = item; + + var name = item.Name; + + if (item.IndexNumber != null) { + name = item.IndexNumber + " - " + name; + } + + Dashboard.setPageTitle(name); + + ItemDetailPage.renderImage(item); + ItemDetailPage.renderOverviewBlock(item); + ItemDetailPage.renderScenes(item); + ItemDetailPage.renderGallery(item); + ItemDetailPage.renderMediaInfo(item); + + $('#itemName', page).html(name); + + Dashboard.hideLoadingMsg(); + }, + + renderImage: function (item) { + + var page = $.mobile.activePage; + + var imageTags = item.ImageTags || {}; + + var html = ''; + + var url; + var useBackgroundColor; + + if (imageTags.Primary) { + + url = ApiClient.getImageUrl(item.Id, { + type: "Primary", + width: 800, + tag: item.ImageTags.Primary + }); + } + else if (item.BackdropImageTags && item.BackdropImageTags.length) { + + url = ApiClient.getImageUrl(item.Id, { + type: "Backdrop", + width: 800, + tag: item.BackdropImageTags[0] + }); + } + else if (imageTags.Thumb) { + + url = ApiClient.getImageUrl(item.Id, { + type: "Thumb", + width: 800, + tag: item.ImageTags.Thumb + }); + } + else if (imageTags.Disc) { + + url = ApiClient.getImageUrl(item.Id, { + type: "Disc", + width: 800, + tag: item.ImageTags.Disc + }); + } + else if (item.MediaType == "Audio") { + url = "css/images/itemDetails/audioDefault.png"; + useBackgroundColor = true; + } + else if (item.MediaType == "Game") { + url = "css/images/itemDetails/gameDefault.png"; + useBackgroundColor = true; + } + else { + url = "css/images/itemDetails/videoDefault.png"; + useBackgroundColor = true; + } + + if (url) { + + var style = useBackgroundColor ? "background-color:" + Dashboard.getRandomMetroColor() + ";" : ""; + + html += ""; + } + + $('#itemImage', page).html(html); + }, + + renderOverviewBlock: function (item) { + + var page = $.mobile.activePage; + + if (item.Taglines && item.Taglines.length) { + $('#itemTagline', page).html(item.Taglines[0]).show(); + } else { + $('#itemTagline', page).hide(); + } + + if (item.Overview) { + $('#itemOverview', page).html(item.Overview).show(); + } else { + $('#itemOverview', page).hide(); + } + + if (item.CommunityRating) { + $('#itemCommunityRating', page).html(ItemDetailPage.getStarRating(item)).show().attr('title', item.CommunityRating); + } else { + $('#itemCommunityRating', page).hide(); + } + + if (MediaPlayer.canPlay(item)) { + $('#btnPlay', page).show(); + $('#playButtonShadow', page).show(); + } else { + $('#btnPlay', page).hide(); + $('#playButtonShadow', page).hide(); + } + + var miscInfo = []; + + if (item.ProductionYear) { + miscInfo.push(item.ProductionYear); + } + + if (item.OfficialRating) { + miscInfo.push(item.OfficialRating); + } + + if (item.RunTimeTicks) { + + var minutes = item.RunTimeTicks / 600000000; + + minutes = minutes || 1; + + miscInfo.push(parseInt(minutes) + "min"); + } + + if (item.DisplayMediaType) { + miscInfo.push(item.DisplayMediaType); + } + + if (item.VideoFormat && item.VideoFormat !== 'Standard') { + miscInfo.push(item.VideoFormat); + } + + $('#itemMiscInfo', page).html(miscInfo.join('     ')); + + ItemDetailPage.renderGenres(item); + ItemDetailPage.renderStudios(item); + }, + + renderGenres: function (item) { + + var page = $.mobile.activePage; + + if (item.Genres && item.Genres.length) { + var elem = $('#itemGenres', page).show(); + + var html = 'Genres:  '; + + for (var i = 0, length = item.Genres.length; i < length; i++) { + + if (i > 0) { + html += '  /  '; + } + + html += '' + item.Genres[i] + ''; + } + + elem.html(html); + + + } else { + $('#itemGenres', page).hide(); + } + }, + + renderStudios: function (item) { + + var page = $.mobile.activePage; + + if (item.Studios && item.Studios.length) { + var elem = $('#itemStudios', page).show(); + + var html = 'Studios:  '; + + for (var i = 0, length = item.Studios.length; i < length; i++) { + + if (i > 0) { + html += '  /  '; + } + + html += '' + item.Studios[i] + ''; + } + + elem.html(html); + + + } else { + $('#itemStudios', page).hide(); + } + }, + + getStarRating: function (item) { + var rating = item.CommunityRating; + + var html = ""; + for (var i = 1; i <= 10; i++) { + if (rating < i - 1) { + html += "
      "; + } + else if (rating < i) { + html += "
      "; + } + else { + html += "
      "; + } + } + + return html; + }, + + renderScenes: function (item) { + + var html = ''; + + var page = $.mobile.activePage; + + if (!item.Chapters || !item.Chapters.length) { + $('#scenesCollapsible', page).hide(); + $('#scenesContent', page).html(html); + return; + } + + for (var i = 0, length = item.Chapters.length; i < length; i++) { + + var chapter = item.Chapters[i]; + + + } + + $('#scenesCollapsible', page).show(); + $('#scenesContent', page).html(html); + }, + + play: function () { + MediaPlayer.play([ItemDetailPage.item]); + }, + + renderGallery: function (item) { + + var page = $.mobile.activePage; + + var imageTags = item.ImageTags || {}; + + var html = ''; + + var downloadWidth = 400; + + if (imageTags.Logo) { + + html += ''; + } + if (imageTags.Thumb) { + + html += ''; + } + if (imageTags.Art) { + + html += ''; + } + if (imageTags.Menu) { + + html += ''; + } + if (imageTags.Disc) { + + html += ''; + } + if (imageTags.Box) { + + html += ''; + } + + if (item.BackdropImageTags) { + + for (var i = 0, length = item.BackdropImageTags.length; i < length; i++) { + html += ''; + } + + } + + $('#galleryContent', page).html(html); + }, + + renderMediaInfo: function(item) { + + var page = $.mobile.activePage; + + if (!item.MediaStreams || !item.MediaStreams.length) { + $('#mediaInfoCollapsible', page).hide(); + return; + } + + $('#mediaInfoCollapsible', page).show(); + } +}; + +$(document).on('pageshow', "#itemDetailPage", ItemDetailPage.onPageShow); diff --git a/Html/scripts/LogPage.js b/Html/scripts/LogPage.js new file mode 100644 index 0000000000..133eb34fbb --- /dev/null +++ b/Html/scripts/LogPage.js @@ -0,0 +1,86 @@ +var LogPage = { + + onPageShow: function () { + + LogPage.startLine = 0; + + $('#logContents', this).html(''); + + $(document).on("websocketmessage", LogPage.onWebSocketMessage).on("websocketopen", LogPage.onWebSocketConnectionChange).on("websocketerror", LogPage.onWebSocketConnectionChange).on("websocketclose", LogPage.onWebSocketConnectionChange); + + LogPage.startInterval(); + + var autoScroll = localStorage.getItem("autoScrollLogPage"); + + if (autoScroll == "true") { + LogPage.updateAutoScroll(true); + } + else if (autoScroll == "false") { + LogPage.updateAutoScroll(false); + } + }, + + onPageHide: function () { + + $(document).off("websocketmessage", LogPage.onWebSocketMessage).off("websocketopen", LogPage.onWebSocketConnectionChange).off("websocketerror", LogPage.onWebSocketConnectionChange).off("websocketclose", LogPage.onWebSocketConnectionChange); + + LogPage.stopInterval(); + }, + + startInterval: function () { + + if (Dashboard.isWebSocketOpen()) { + Dashboard.sendWebSocketMessage("LogFileStart", "0,2000"); + } + }, + + stopInterval: function () { + + if (Dashboard.isWebSocketOpen()) { + Dashboard.sendWebSocketMessage("LogFileStop"); + } + }, + + onWebSocketConnectionChange: function () { + LogPage.stopInterval(); + LogPage.startInterval(); + }, + + onWebSocketMessage: function (e, msg) { + + if (msg.MessageType == "LogFile") { + LogPage.appendLines(msg.Data); + } + }, + + appendLines: function (lines) { + + if (!lines.length) { + return; + } + + LogPage.startLine += lines.length; + + lines = lines.join('\n') + '\n'; + + var elem = $('#logContents', $.mobile.activePage).append(lines)[0]; + + elem.style.height = (elem.scrollHeight) + 'px'; + + if ($('#chkAutoScroll', $.mobile.activePage).checked()) { + $('html, body').animate({ scrollTop: $(document).height() }, 'slow'); + } + }, + + updateAutoScroll: function (value) { + + var page = $.mobile.activePage; + + $('#chkAutoScrollBottom', page).checked(value).checkboxradio('refresh'); + $('#chkAutoScroll', page).checked(value).checkboxradio('refresh'); + + localStorage.setItem("autoScrollLogPage", value.toString()); + } +}; + +$(document).on('pageshow', "#logPage", LogPage.onPageShow).on('pagehide', "#logPage", LogPage.onPageHide); \ No newline at end of file diff --git a/Html/scripts/LoginPage.js b/Html/scripts/LoginPage.js new file mode 100644 index 0000000000..46e7d53cca --- /dev/null +++ b/Html/scripts/LoginPage.js @@ -0,0 +1,112 @@ +var LoginPage = { + + onPageShow: function () { + Dashboard.showLoadingMsg(); + + ApiClient.getAllUsers().done(LoginPage.loadUserList); + }, + + getLastSeenText: function (lastActivityDate) { + + if (!lastActivityDate) { + return ""; + } + + return "Last seen " + humane_date(lastActivityDate); + }, + + getImagePath: function (user) { + + if (!user.PrimaryImageTag) { + return "css/images/logindefault.png"; + } + + return ApiClient.getUserImageUrl(user.Id, { + width: 240, + tag: user.PrimaryImageTag, + type: "Primary" + }); + }, + + authenticateUserLink: function (link) { + + LoginPage.authenticateUser(link.getAttribute('data-username'), link.getAttribute('data-userid')); + }, + + authenticateUser: function (username, userId, password) { + + Dashboard.showLoadingMsg(); + + ApiClient.authenticateUser(userId, password).done(function () { + + Dashboard.setCurrentUser(userId); + + window.location = "index.html?u=" + userId; + + }).fail(function () { + Dashboard.hideLoadingMsg(); + + setTimeout(function () { + Dashboard.showError("Invalid user or password."); + }, 300); + }); + }, + + loadUserList: function (users) { + var html = ""; + + for (var i = 0, length = users.length; i < length; i++) { + var user = users[i]; + + var linkId = "lnkUser" + i; + + var background = Dashboard.getRandomMetroColor(); + + if (user.HasPassword) { + html += ""; + } else { + html += ""; + } + + if (user.PrimaryImageTag) { + + var imgUrl = ApiClient.getUserImageUrl(user.Id, { + width: 500, + tag: user.PrimaryImageTag, + type: "Primary" + }); + + html += ''; + } else { + html += ''; + } + + html += '
      '; + + html += '
      '; + html += '

      ' + user.Name + '

      '; + html += '

      ' + LoginPage.getLastSeenText(user.LastActivityDate) + '

      '; + html += '
      '; + + html += '
      '; + html += '
      '; + } + + $('#divUsers', '#loginPage').html(html); + + Dashboard.hideLoadingMsg(); + }, + + onSubmit: function () { + $('#popupLogin', '#loginPage').popup('close'); + + var link = $('#' + LoginPage.authenticatingLinkId)[0]; + + LoginPage.authenticateUser(link.getAttribute('data-username'), link.getAttribute('data-userid'), $('#pw', '#loginPage').val()); + + // Disable default form submission + return false; + } +}; + +$(document).on('pageshow', "#loginPage", LoginPage.onPageShow); diff --git a/Html/scripts/MediaLibraryPage.js b/Html/scripts/MediaLibraryPage.js new file mode 100644 index 0000000000..4f4d119d83 --- /dev/null +++ b/Html/scripts/MediaLibraryPage.js @@ -0,0 +1,272 @@ +var MediaLibraryPage = { + + onPageShow: function () { + + MediaLibraryPage.lastVirtualFolderName = ""; + + MediaLibraryPage.reloadLibrary(); + }, + + reloadLibrary: function () { + + Dashboard.showLoadingMsg(); + + var userId = getParameterByName("userId"); + + var page = $.mobile.activePage; + + if (userId) { + + $('#userProfileNavigation', page).show(); + + ApiClient.getUser(userId).done(function (user) { + + Dashboard.setPageTitle(user.Name); + + $('#fldUseDefaultLibrary', page).show(); + + $('#chkUseDefaultLibrary', page).checked(!user.Configuration.UseCustomLibrary).checkboxradio("refresh"); + + if (user.Configuration.UseCustomLibrary) { + + ApiClient.getVirtualFolders(userId).done(MediaLibraryPage.reloadVirtualFolders); + $('#divMediaLibrary', page).show(); + } else { + $('#divMediaLibrary', page).hide(); + Dashboard.hideLoadingMsg(); + } + + }); + + } else { + + $('#userProfileNavigation', page).hide(); + ApiClient.getVirtualFolders().done(MediaLibraryPage.reloadVirtualFolders); + + $('#fldUseDefaultLibrary', page).hide(); + $('#divMediaLibrary', page).show(); + Dashboard.setPageTitle("Media Library"); + } + }, + + reloadVirtualFolders: function (virtualFolders) { + + var page = $.mobile.activePage; + + if (virtualFolders) { + MediaLibraryPage.virtualFolders = virtualFolders; + } else { + virtualFolders = MediaLibraryPage.virtualFolders; + } + + var html = ''; + + for (var i = 0, length = virtualFolders.length; i < length; i++) { + + var virtualFolder = virtualFolders[i]; + + var isCollapsed = MediaLibraryPage.lastVirtualFolderName != virtualFolder.Name; + + html += MediaLibraryPage.getVirtualFolderHtml(virtualFolder, isCollapsed, i); + } + + $('#divVirtualFolders', page).html(html).trigger('create'); + + Dashboard.hideLoadingMsg(); + }, + + getVirtualFolderHtml: function (virtualFolder, isCollapsed, index) { + + isCollapsed = isCollapsed ? "true" : "false"; + var html = '
      '; + + html += '

      ' + virtualFolder.Name + '

      '; + + html += '
        '; + + html += '
      • Media Locations'; + html += ''; + html += '
      • '; + + for (var i = 0, length = virtualFolder.Locations.length; i < length; i++) { + + var location = virtualFolder.Locations[i]; + html += '
      • '; + html += '' + location + ''; + html += ''; + html += '
      • '; + } + html += '
      '; + + html += '

      '; + html += ''; + html += ''; + html += '

      '; + + html += '
      '; + + return html; + }, + + setUseDefaultMediaLibrary: function (useDefaultLibrary) { + + Dashboard.showLoadingMsg(); + + var userId = getParameterByName("userId"); + + ApiClient.getUser(userId).done(function (user) { + + user.Configuration.UseCustomLibrary = !useDefaultLibrary; + + ApiClient.updateUser(user).done(MediaLibraryPage.reloadLibrary); + }); + }, + + addVirtualFolder: function () { + + MediaLibraryPage.getTextValue("Add Media Collection", "Name:", "", function (name) { + + var userId = getParameterByName("userId"); + + MediaLibraryPage.lastVirtualFolderName = name; + + ApiClient.addVirtualFolder(name, userId).done(MediaLibraryPage.processOperationResult); + + }); + }, + + addMediaLocation: function (virtualFolderIndex) { + + MediaLibraryPage.selectDirectory(function (path) { + + if (path) { + + var virtualFolder = MediaLibraryPage.virtualFolders[virtualFolderIndex]; + + MediaLibraryPage.lastVirtualFolderName = virtualFolder.Name; + + var userId = getParameterByName("userId"); + + ApiClient.addMediaPath(virtualFolder.Name, path, userId).done(MediaLibraryPage.processOperationResult); + } + + }); + }, + + selectDirectory: function (callback) { + + Dashboard.selectDirectory({callback: callback}); + }, + + getTextValue: function (header, label, initialValue, callback) { + + var page = $.mobile.activePage; + + var popup = $('#popupEnterText', page); + + $('h3', popup).html(header); + $('label', popup).html(label); + $('#txtValue', popup).val(initialValue); + + popup.popup("open").on("popupafterclose", function () { + + $(this).off("popupafterclose").off("click"); + + $('#textEntryForm', this).off("submit"); + + }); + + $('#textEntryForm', popup).on('submit', function () { + + if (callback) { + callback($('#txtValue', popup).val()); + } + + return false; + }); + }, + + renameVirtualFolder: function (button) { + + var folderIndex = button.getAttribute('data-folderindex'); + var virtualFolder = MediaLibraryPage.virtualFolders[folderIndex]; + + MediaLibraryPage.lastVirtualFolderName = virtualFolder.Name; + + MediaLibraryPage.getTextValue(virtualFolder.Name, "Rename " + virtualFolder.Name, virtualFolder.Name, function (newName) { + + if (virtualFolder.Name != newName) { + + var userId = getParameterByName("userId"); + + ApiClient.renameVirtualFolder(virtualFolder.Name, newName, userId).done(MediaLibraryPage.processOperationResult); + } + }); + }, + + deleteVirtualFolder: function (button) { + + var folderIndex = button.getAttribute('data-folderindex'); + var virtualFolder = MediaLibraryPage.virtualFolders[folderIndex]; + + var parent = $(button).parents('.collapsibleVirtualFolder'); + + var locations = $('.lnkMediaLocation', parent).map(function () { + return this.innerHTML; + }).get(); + + var msg = "Are you sure you wish to remove " + virtualFolder.Name + "?"; + + if (locations.length) { + msg += "

      The following media locations will be removed from your library:

      "; + msg += locations.join("
      "); + } + + MediaLibraryPage.lastVirtualFolderName = virtualFolder.Name; + + Dashboard.confirm(msg, "Remove Media Folder", function (confirmResult) { + + if (confirmResult) { + + var userId = getParameterByName("userId"); + + ApiClient.removeVirtualFolder(virtualFolder.Name, userId).done(MediaLibraryPage.processOperationResult); + } + + }); + }, + + deleteMediaLocation: function (button) { + + var folderIndex = button.getAttribute('data-folderindex'); + var index = parseInt(button.getAttribute('data-index')); + + var virtualFolder = MediaLibraryPage.virtualFolders[folderIndex]; + + MediaLibraryPage.lastVirtualFolderName = virtualFolder.Name; + + var location = virtualFolder.Locations[index]; + + Dashboard.confirm("Are you sure you wish to remove " + location + "?", "Remove Media Location", function (confirmResult) { + + if (confirmResult) { + + var userId = getParameterByName("userId"); + + ApiClient.removeMediaPath(virtualFolder.Name, location, userId).done(MediaLibraryPage.processOperationResult); + } + }); + }, + + processOperationResult: function (result) { + Dashboard.hideLoadingMsg(); + + var page = $.mobile.activePage; + + $('#popupEnterText', page).popup("close"); + $('#popupDirectoryPicker', page).popup("close"); + MediaLibraryPage.reloadLibrary(); + } +}; + +$(document).on('pageshow', ".mediaLibraryPage", MediaLibraryPage.onPageShow); \ No newline at end of file diff --git a/Html/scripts/MediaPlayer.js b/Html/scripts/MediaPlayer.js new file mode 100644 index 0000000000..bf3733ffdc --- /dev/null +++ b/Html/scripts/MediaPlayer.js @@ -0,0 +1,170 @@ +var MediaPlayer = { + + canPlay: function (item) { + + if (item.MediaType === "Video") { + + var media = document.createElement('video'); + + if (media.canPlayType) { + + return media.canPlayType('video/mp2t').replace(/no/, '') || media.canPlayType('video/webm').replace(/no/, '') || media.canPlayType('video/ogv').replace(/no/, ''); + } + + return false; + } + + if (item.MediaType === "Audio") { + + var media = document.createElement('audio'); + + if (media.canPlayType) { + return media.canPlayType('audio/mpeg').replace(/no/, '') || media.canPlayType('audio/aac').replace(/no/, ''); + } + + return false; + } + + return false; + }, + + play: function (items) { + + if (MediaPlayer.isPlaying()) { + MediaPlayer.stop(); + } + + var item = items[0]; + + var mediaElement; + + if (item.MediaType === "Video") { + + mediaElement = MediaPlayer.playVideo(items); + } + + else if (item.MediaType === "Audio") { + + mediaElement = MediaPlayer.playAudio(items); + } + + if (!mediaElement) { + return; + } + + MediaPlayer.mediaElement = mediaElement; + + var nowPlayingBar = $('#nowPlayingBar').show(); + + if (items.length > 1) { + $('#previousTrackButton', nowPlayingBar)[0].disabled = false; + $('#nextTrackButton', nowPlayingBar)[0].disabled = false; + } else { + $('#previousTrackButton', nowPlayingBar)[0].disabled = true; + $('#nextTrackButton', nowPlayingBar)[0].disabled = true; + } + }, + + playAudio: function (items) { + var item = items[0]; + + var baseParams = { + id: item.Id, + audioChannels: 2, + audioBitrate: 128000 + }; + + var mp3Url = ApiClient.getUrl('audio.mp3', $.extend({}, baseParams, { + audioCodec: 'mp3' + })); + + var aacUrl = ApiClient.getUrl('audio.aac', $.extend({}, baseParams, { + audioCodec: 'aac' + })); + + var webmUrl = ApiClient.getUrl('audio.webma', $.extend({}, baseParams, { + audioCodec: 'Vorbis' + })); + + var oggUrl = ApiClient.getUrl('audio.oga', $.extend({}, baseParams, { + audioCodec: 'Vorbis' + })); + + var html = ''; + html += '