Pushing missing changes

This commit is contained in:
LukePulverenti 2013-02-20 20:33:05 -05:00
parent 1227b75260
commit 331a8d8366
129 changed files with 8370 additions and 15 deletions

80
Html/addPlugin.html Normal file
View File

@ -0,0 +1,80 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="addPluginPage" data-role="page" class="page type-interior pluginConfigurationPage">
<div data-role="content">
<div class="content-primary">
<p>
<a data-role="button" data-icon="arrow-left" data-inline="true" data-mini="true" data-theme="b" href="pluginCatalog.html">Plugin Catalog</a>
</p>
<form id="addPluginForm">
<p id="tagline" style="font-style: italic;"></p>
<p id="pPreviewImage" style="text-align: center; margin: 2em 0;"></p>
<p id="overview"></p>
<div data-role="collapsible" data-content-theme="c" data-collapsed="false" style="margin-top: 2em;" data-theme="a">
<h3>Install</h3>
<p id="pCurrentVersion">
</p>
<p>
<label for="selectVersion">Select version to install:</label>
<select id="selectVersion" name="selectVersion"></select>
</p>
<p>
<button id="btnInstall" type="submit" data-icon="download" data-theme="b">Install</button>
</p>
</div>
</form>
<form name="_xclick" target="_blank" action="https://www.paypal.com/cgi-bin/webscr" method="post">
<div class="premiumPackage" data-role="collapsible" data-content-theme="c" data-collapsed="false" style="margin-top: 2em; display: none" data-theme="a">
<h3>Registration</h3>
<p id="regStatus">
</p>
<p id="regInfo">
</p>
<p id="regPrice">
</p>
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" id="payPalEmail" name="business" value="mb_1358534950_biz@reedsplace.com">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" id="featureName" name="item_name" value="MBSupporter">
<input type="hidden" id="amount" name="amount" value="10">
<input type="hidden" id="featureId" name="item_number" value="MBSupporter">
<input type="hidden" name="notify_url" value="http://mb3admin.com/admin/service/services/ppipn.php">
<input type="hidden" name="return" id ="paypalReturnUrl" value="#">
<a data-role="button" id="ppButton" onclick="_xclick.submit();"><img src="css/images/registerpp.png"/></a>
<p id="noEmail" style="display: none"><strong>This developer has not provided a PayPal email. Please see their
website for registration information.</strong>
</p>
</div>
<div data-role="collapsible" data-content-theme="c" data-collapsed="false" style="margin-top: 2em;" data-theme="a">
<h3>Developer Info</h3>
<p id="developer"></p>
<p id="pViewWebsite" style="display: none;">
<a href="#" data-rel="external" target="_blank">View Website</a>
</p>
</div>
<div data-role="collapsible" data-content-theme="c" style="margin-top: 2em;" data-theme="a">
<h3>Revision History</h3>
<div id="revisionHistory"></div>
</div>
</form>
</div>
</div>
<script type="text/javascript">
$('#addPluginForm').on('submit', AddPluginPage.onSubmit);
</script>
</div>
</body>
</html>

56
Html/advanced.html Normal file
View File

@ -0,0 +1,56 @@
<!DOCTYPE html>
<html>
<head>
<title>Advanced</title>
</head>
<body>
<div id="advancedConfigurationPage" data-role="page" class="page type-interior">
<div data-role="content">
<div class="content-primary">
<form id="advancedConfigurationForm">
<ul data-role="listview" class="ulForm">
<li>
<input type="checkbox" id="chkRunAtStartup" name="chkRunAtStartup" />
<label for="chkRunAtStartup">Run server at startup</label>
</li>
<li>
<label for="txtPortNumber">Http server port number: </label>
<input type="number" id="txtPortNumber" name="txtPortNumber" pattern="[0-9]*" required="required" min="1" />
</li>
<li id="fldWebSocketPortNumber" style="display:none;">
<label for="txtWebSocketPortNumber">Web socket port number: </label>
<input type="number" id="txtWebSocketPortNumber" name="txtWebSocketPortNumber" pattern="[0-9]*" required="required" min="1" />
</li>
<li>
<input type="checkbox" id="chkEnableDeveloperTools" name="chkEnableDeveloperTools" />
<label for="chkEnableDeveloperTools">Enable developer tools</label>
<div class="fieldDescription">
When enabled, developer tools will be available from the system tray.
</div>
</li>
<li>
<input type="checkbox" id="chkDebugLog" name="chkDebugLog" />
<label for="chkDebugLog">Enable debug logging </label>
</li>
<li>
<button type="submit" data-theme="b" data-icon="ok">
Save
</button>
<button type="button" onclick="Dashboard.navigate('dashboard.html');" data-icon="delete">
Cancel
</button>
</li>
</ul>
</form>
</div>
</div>
<script type="text/javascript">
$('#advancedConfigurationForm').on('submit', AdvancedConfigurationPage.onSubmit);
</script>
</div>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<title>Metadata</title>
</head>
<body>
<div id="advancedMetadataConfigurationPage" data-role="page" class="page type-interior">
<div data-role="content">
<div class="content-primary">
<div data-role="controlgroup" data-type="horizontal" class="localnav" data-mini="true">
<a href="metadata.html" data-role="button">Basics</a>
<a href="metadataImages.html" data-role="button">Images</a>
<a href="advancedMetadata.html" data-role="button" class="ui-btn-active">Advanced</a>
</div>
<form id="advancedMetadataConfigurationForm">
<ul data-role="listview" class="ulForm">
<li>
<label>Disable internet providers for:</label>
<div id="divItemTypes"></div>
</li>
<li>
<button type="submit" data-theme="b">
Save
</button>
<button type="button" onclick="Dashboard.navigate('dashboard.html');">
Cancel
</button>
</li>
</ul>
</form>
</div>
</div>
<script type="text/javascript">
$('#advancedMetadataConfigurationForm').on('submit', AdvancedMetadataConfigurationPage.onSubmit);
</script>
</div>
</body>
</html>

BIN
Html/css/images/bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
Html/css/images/home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 916 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
Html/css/images/stars.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

897
Html/css/site.css Normal file

File diff suppressed because one or more lines are too long

52
Html/dashboard.html Normal file
View File

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html>
<head>
<title>Dashboard</title>
</head>
<body>
<div id="dashboardPage" data-role="page" class="page type-interior">
<div data-role="content">
<div class="content-primary">
<div class="readOnlyContent">
<div data-role="collapsible" data-content-theme="c" data-collapsed="false" style="margin-top: 2em;">
<h3>Server Information</h3>
<div>
<p>
Version <span id="appVersionNumber"></span>
</p>
<p id="pUpToDate" style="display: none;">
<img src="css/images/checkMarkGreen.png" style="height: 20px; margin-right: 3px; position: relative; top: 4px;" />
Media Browser Server is up to date
</p>
<div id="pUpdateNow" style="display: none;">
<p><strong>A new version of Media Browser Server is available!</strong></p>
<p id="newVersionNumber"></p>
<button id="btnUpdateApplication" type="button" data-icon="download" data-theme="b" onclick="DashboardPage.updateApplication();">Update Now</button>
</div>
</div>
</div>
<div data-role="collapsible" data-content-theme="c" data-collapsed="false" style="margin-top: 2em; display: none;" id="collapsiblePluginUpdates">
<h3>Plugin Information</h3>
<div id="pPluginUpdates"></div>
</div>
<div data-role="collapsible" data-content-theme="c" data-collapsed="false" style="margin-top: 2em;">
<h3>Active Connections</h3>
<div id="divConnections">
</div>
</div>
<div data-role="collapsible" data-content-theme="c" data-collapsed="false" style="margin-top: 2em;">
<h3>Running Tasks</h3>
<div id="divRunningTasks">
</div>
<p><a href="scheduledTasks.html">Manage Scheduled Tasks</a></p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

63
Html/editUser.html Normal file
View File

@ -0,0 +1,63 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="editUserPage" data-role="page" class="page type-interior userProfilesConfigurationPage">
<div data-role="content">
<div class="content-primary">
<div data-role="controlgroup" data-type="horizontal" class="localnav" id="userProfileNavigation" style="display: none;" data-mini="true">
<a href="#" data-role="button" class="ui-btn-active">Profile</a>
<a href="#" data-role="button" onclick="Dashboard.navigate('userImage.html', true);">Image</a>
<a href="#" data-role="button" onclick="Dashboard.navigate('updatePassword.html', true);">Password</a>
<a href="#" data-role="button" onclick="Dashboard.navigate('library.html', true);">Media Library</a>
</div>
<form id="editUserProfileForm">
<ul data-role="listview" class="ulForm">
<li id="fldUserName">
<label for="txtUserName">Name: </label>
<input id="txtUserName" name="txtUserName" required="required" type="text" />
</li>
<li id="fldMaxParentalRating" style="display: none;">
<label for="selectMaxParentalRating">Max parental rating:</label>
<select name="selectMaxParentalRating" id="selectMaxParentalRating"></select>
</li>
<li id="fldIsAdmin" style="display: none;">
<input type="checkbox" id="chkIsAdmin" name="chkIsAdmin" />
<label for="chkIsAdmin">Allow this user to manage the server</label>
</li>
</ul>
<h2>Video Playback Settings</h2>
<ul data-role="listview" class="ulForm">
<li>
<label for="selectAudioLanguage">Audio language preference: </label>
<select name="selectAudioLanguage" id="selectAudioLanguage"></select>
</li>
<li>
<label for="selectSubtitleLanguage">Subtitle language preference: </label>
<select name="selectSubtitleLanguage" id="selectSubtitleLanguage"></select>
</li>
<li>
<input type="checkbox" id="chkForcedSubtitlesOnly" name="chkForcedSubtitlesOnly" />
<label for="chkForcedSubtitlesOnly">Display only forced subtitles</label>
</li>
<li>
<button type="submit" data-theme="b" data-icon="ok">
Save
</button>
<button type="button" onclick="history.back();" data-icon="delete">
Cancel
</button>
</li>
</ul>
</form>
</div>
</div>
<script type="text/javascript">
$('#editUserProfileForm').on('submit', EditUserPage.onSubmit);
</script>
</div>
</body>
</html>

BIN
Html/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

33
Html/index.html Normal file
View File

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<title>Media Browser</title>
</head>
<body>
<div id="indexPage" data-role="page" class="page type-home libraryPage" data-theme="a">
<div data-role="content">
<h1>What's New <a href="#" class="imageLink">
<img src="css/images/rightArrow.png" /></a></h1>
<div id="divWhatsNew"></div>
<div id="divResumable" style="display: none;">
<h1>Resume <a href="#" class="imageLink">
<img src="css/images/rightArrow.png" /></a></h1>
<div id="divResumableItems"></div>
</div>
<h1>My Library <a href="#" class="imageLink">
<img src="css/images/rightArrow.png" /></a></h1>
<div id="divMyLibrary"></div>
<h1>Collections <a href="#" class="imageLink">
<img src="css/images/rightArrow.png" /></a></h1>
<div id="divCollections"></div>
</div>
</div>
</body>
</html>

66
Html/itemDetails.html Normal file
View File

@ -0,0 +1,66 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="itemDetailPage" data-role="page" class="page libraryPage" data-theme="a">
<div data-role="content" style="padding-top: 0;">
<h1 id="itemName" style="padding-left: 10px; margin: 0;"></h1>
<div style="padding: 10px;">
<div class="itemImageBlock">
<div id="itemMedia" style="position: relative;">
<div id="itemImage"></div>
<div id="playButtonShadow" style="display: none; height: 48px; position: absolute; bottom: 0; left: 0; right: 0; background: black; opacity: .75;">
</div>
<button id="btnPlay" type="button" class="imageButton" style="display: none; position: absolute; bottom: 5px; left: 10px;" data-role="none" title="Play" onclick="ItemDetailPage.play();">
<img src="css/images/media/playCircle.png" style="height: 28px;" />
</button>
</div>
</div>
<div class="itemDetailBlock">
<p id="itemTagline" style="font-style: italic;"></p>
<p id="itemOverview"></p>
<p id="itemCommunityRating"></p>
<p id="itemMiscInfo" style="color: #ddd; font-size: 14px;"></p>
<p id="itemGenres">
</p>
<p id="itemStudios">
</p>
</div>
</div>
<div data-role="collapsible" data-content-theme="a" id="mediaInfoCollapsible">
<h3>Media Info</h3>
<div id="mediaInfoContent"></div>
</div>
<div data-role="collapsible" data-content-theme="a" id="scenesCollapsible">
<h3>Scenes</h3>
<div id="scenesContent"></div>
</div>
<div data-role="collapsible" data-content-theme="a">
<h3>Special Features</h3>
<p>I'm the collapsible content. By default I'm closed, but you can click the header to open me.</p>
</div>
<div data-role="collapsible" data-content-theme="a">
<h3>Trailers</h3>
<p>I'm the collapsible content. By default I'm closed, but you can click the header to open me.</p>
</div>
<div data-role="collapsible" data-content-theme="a">
<h3>Cast & Crew</h3>
<p>I'm the collapsible content. By default I'm closed, but you can click the header to open me.</p>
</div>
<div data-role="collapsible" data-content-theme="a">
<h3>Gallery</h3>
<div id="galleryContent"></div>
</div>
</div>
</div>
</body>
</html>

57
Html/library.html Normal file
View File

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html>
<head>
<title> </title>
</head>
<body>
<div id="mediaLibraryPage" data-role="page" class="page type-interior mediaLibraryPage">
<div data-role="content">
<div class="content-primary">
<div data-role="controlgroup" data-type="horizontal" class="localnav" id="userProfileNavigation" style="display: none;" data-mini="true">
<a href="#" data-role="button" onclick="Dashboard.navigate('editUser.html', true);">Profile</a>
<a href="#" data-role="button" onclick="Dashboard.navigate('userImage.html', true);">Image</a>
<a href="#" data-role="button" onclick="Dashboard.navigate('updatePassword.html', true);">Password</a>
<a href="#" data-role="button" class="ui-btn-active">Media Library</a>
</div>
<div class="readOnlyContent">
<p id="fldUseDefaultLibrary" style="display: none;">
<input type="checkbox" id="chkUseDefaultLibrary" name="chkUseDefaultLibrary" onchange="MediaLibraryPage.setUseDefaultMediaLibrary(this.checked);" />
<label for="chkUseDefaultLibrary">Use default media library</label>
</p>
<div id="divMediaLibrary">
<p>Below are your media collections. Expand a collection to add or remove media locations assigned to it.</p>
<p>
<button type="button" data-icon="plus" onclick="MediaLibraryPage.addVirtualFolder();">Add media collection</button>
</p>
<div id="divVirtualFolders"></div>
</div>
</div>
</div>
</div>
<div data-role="popup" id="popupEnterText" class="ui-corner-all popup">
<div class="ui-corner-top ui-bar-a" style="text-align: center; padding: 0 20px;">
<h3>Rename</h3>
</div>
<div data-role="content" class="ui-corner-bottom ui-content">
<form id="textEntryForm">
<label for="txtValue">New name:</label>
<input type="text" name="txtValue" id="txtValue" required="required" />
<p>
<button type="submit" data-theme="b" data-icon="ok">
Ok
</button>
<button type="button" data-icon="delete" onclick="$(this).parents('.popup').popup('close');">
Cancel
</button>
</p>
</form>
</div>
</div>
</div>
</body>
</html>

30
Html/log.html Normal file
View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<title>Log File</title>
</head>
<body>
<div id="logPage" data-role="page" class="page type-interior">
<div data-role="content">
<div class="content-primary">
<div data-role="controlgroup" data-type="horizontal" class="localnav" data-mini="true">
<a href="support.html" data-role="button">General</a>
<a href="log.html" data-role="button" class="ui-btn-active">View Log</a>
<a href="supporter.html" data-role="button">Become a Supporter</a>
<a href="supporterKey.html" data-role="button">Supporter Key</a>
</div>
<p>
<label for="chkAutoScroll">Auto-scroll</label>
<input type="checkbox" id="chkAutoScroll" onchange="LogPage.updateAutoScroll(this.checked);" name="chkAutoScroll" data-inline="true" />
</p>
<textarea id="logContents" class="pre" style="overflow-y:hidden;"></textarea>
<p>
<label for="chkAutoScrollBottom">Auto-scroll</label>
<input type="checkbox" id="chkAutoScrollBottom" name="chkAutoScrollBottom" onchange="LogPage.updateAutoScroll(this.checked);" data-inline="true" />
</p>
</div>
</div>
</div>
</body>
</html>

39
Html/login.html Normal file
View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<title>Sign In</title>
</head>
<body>
<div id="loginPage" data-role="page" class="page standalonePage">
<div data-role="content">
<div id="divUsers" style="margin: 50px 20px 20px; text-align: center;"></div>
</div>
<div data-role="popup" id="popupLogin" class="ui-corner-all popup">
<form id="loginForm">
<div class="ui-corner-top ui-bar-a" style="text-align: center;">
<h3>Please sign in</h3>
</div>
<div data-role="content" class="ui-corner-bottom ui-content">
<label for="pw" class="ui-hidden-accessible">Password:</label>
<input type="password" name="pw" id="pw" value="" placeholder="password" />
<p>
<button type="submit" data-theme="b" data-icon="ok">
Sign in
</button>
<button type="button" data-icon="delete" onclick="$(this).parents('.popup').popup('close');">
Cancel
</button>
</p>
</div>
</form>
</div>
<script type="text/javascript">
$('#loginForm').on('submit', LoginPage.onSubmit);
</script>
</div>
</body>
</html>

59
Html/metadata.html Normal file
View File

@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<title>Metadata</title>
</head>
<body>
<div id="metadataConfigurationPage" data-role="page" class="page type-interior">
<div data-role="content">
<div class="content-primary">
<div data-role="controlgroup" data-type="horizontal" class="localnav" data-mini="true">
<a href="metadata.html" data-role="button" class="ui-btn-active">Basics</a>
<a href="metadataImages.html" data-role="button">Images</a>
<a href="advancedMetadata.html" data-role="button">Advanced</a>
</div>
<form id="metadataConfigurationForm">
<ul data-role="listview" class="ulForm">
<li>
<input type="checkbox" id="chkEnableInternetProviders" name="chkEnableInternetProviders" />
<label for="chkEnableInternetProviders">Download metadata from the internet </label>
</li>
<li>
<input type="checkbox" id="chkSaveLocal" name="chkSaveLocal" />
<label for="chkSaveLocal">Save metadata within media folders </label>
</li>
<li>
<label for="txtRefreshDays">Metadata refresh period (days): </label>
<input type="number" id="txtRefreshDays" name="txtRefreshDays" pattern="[0-9]*" required="required" min="1" />
</li>
<li>
<label for="selectLanguage">Preferred language: </label>
<select name="selectLanguage" id="selectLanguage"></select>
</li>
<li>
<label for="selectCountry">Country: </label>
<select name="selectCountry" id="selectCountry"></select>
</li>
<li>
<button type="submit" data-theme="b">
Save
</button>
<button type="button" onclick="Dashboard.navigate('dashboard.html');">
Cancel
</button>
</li>
</ul>
</form>
</div>
</div>
<script type="text/javascript">
$('#metadataConfigurationForm').on('submit', MetadataConfigurationPage.onSubmit);
</script>
</div>
</body>
</html>

120
Html/metadataImages.html Normal file
View File

@ -0,0 +1,120 @@
<!DOCTYPE html>
<html>
<head>
<title>Metadata</title>
</head>
<body>
<div id="metadataImagesConfigurationPage" data-role="page" class="page type-interior">
<div data-role="content">
<div class="content-primary">
<div data-role="controlgroup" data-type="horizontal" class="localnav" data-mini="true">
<a href="metadata.html" data-role="button">Basics</a>
<a href="metadataImages.html" data-role="button" class="ui-btn-active">Images</a>
<a href="advancedMetadata.html" data-role="button">Advanced</a>
</div>
<form id="metadataImagesConfigurationForm">
<ul data-role="listview" class="ulForm">
<li>
<input type="checkbox" id="chkRefreshItemImages" name="chkRefreshItemImages" />
<label for="chkRefreshItemImages">Refresh existing images </label>
<div class="fieldDescription">
When enabled, images will be refreshed periodically
</div>
</li>
<li>
<label for="txtNumbackdrops">Max number of backdrops per item: </label>
<input type="number" id="txtNumbackdrops" name="txtNumbackdrops" pattern="[0-9]*" required="required" min="1" />
</li>
<li>
<label>Enable additional image downloading:</label>
<div data-role="controlgroup">
<input type="checkbox" data-mini="true" id="chkDownloadMovieArt" name="chkDownloadMovieArt" />
<label for="chkDownloadMovieArt">Movie Art</label>
<input type="checkbox" data-mini="true" id="chkDownloadMovieBanner" name="chkDownloadMovieBanner" />
<label for="chkDownloadMovieBanner">Movie Banner</label>
<input type="checkbox" data-mini="true" id="chkDownloadMovieDisc" name="chkDownloadMovieDisc" />
<label for="chkDownloadMovieDisc">Movie Disc</label>
<input type="checkbox" data-mini="true" id="chkDownloadMovieLogo" name="chkDownloadMovieLogo" />
<label for="chkDownloadMovieLogo">Movie Logo</label>
<input type="checkbox" data-mini="true" id="chkDownloadMovieThumb" name="chkDownloadMovieThumb" />
<label for="chkDownloadMovieThumb">Movie Thumb</label>
<input type="checkbox" data-mini="true" id="chKDownloadTVArt" name="chKDownloadTVArt" />
<label for="chKDownloadTVArt">TV Series Art</label>
<input type="checkbox" data-mini="true" id="chkDownloadTVBanner" name="chkDownloadTVBanner" />
<label for="chkDownloadTVBanner">TV Series Banner</label>
<input type="checkbox" data-mini="true" id="chkDownloadTVLogo" name="chkDownloadTVLogo" />
<label for="chkDownloadTVLogo">TV Series Logo</label>
<input type="checkbox" data-mini="true" id="chkDownloadTVThumb" name="chkDownloadTVThumb" />
<label for="chkDownloadTVThumb">TV Series Thumb</label>
<input type="checkbox" data-mini="true" id="chkDownloadSeasonBackdrops" name="chkDownloadSeasonBackdrops" />
<label for="chkDownloadSeasonBackdrops">TV Season Backdrops</label>
<input type="checkbox" data-mini="true" id="chkDownloadSeasonBanner" name="chkDownloadSeasonBanner" />
<label for="chkDownloadSeasonBanner">TV Season Banner</label>
<input type="checkbox" data-mini="true" id="chkDownloadSeasonThumb" name="chkDownloadSeasonThumb" />
<label for="chkDownloadSeasonThumb">TV Season Thumb</label>
</div>
</li>
<li>
<label for="selectTmdbPosterDownloadSize">Tmdb poster download size: </label>
<select id="selectTmdbPosterDownloadSize" name="selectTmdbPosterDownloadSize">
<option value="original">original</option>
<option value="w92">w92</option>
<option value="w154">w154</option>
<option value="w185">w185</option>
<option value="w342">w342</option>
<option value="w500">w500</option>
</select>
</li>
<li>
<label for="selectTmdbBackdropDownloadSize">Tmdb backdrop download size: </label>
<select id="selectTmdbBackdropDownloadSize" name="selectTmdbBackdropDownloadSize">
<option value="original">original</option>
<option value="w380">w380</option>
<option value="w780">w780</option>
<option value="w1280">w1280</option>
</select>
</li>
<li>
<label for="selectTmdbPersonImageDownloadSize">Tmdb person image download size: </label>
<select id="selectTmdbPersonImageDownloadSize" name="selectTmdbPersonImageDownloadSize">
<option value="original">original</option>
<option value="w45">w45</option>
<option value="w185">w185</option>
<option value="h632">h632</option>
</select>
</li>
<li>
<button type="submit" data-theme="b">
Save
</button>
<button type="button" onclick="Dashboard.navigate('dashboard.html');">
Cancel
</button>
</li>
</ul>
</form>
</div>
</div>
<script type="text/javascript">
$('#metadataImagesConfigurationForm').on('submit', MetadataImagesPage.onSubmit);
</script>
</div>
</body>
</html>

22
Html/pluginCatalog.html Normal file
View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<title>Plugins</title>
</head>
<body>
<div id="pluginCatalogPage" data-role="page" class="page type-interior pluginConfigurationPage">
<div data-role="content">
<div class="content-primary">
<div data-role="controlgroup" data-type="horizontal" class="localnav" data-mini="true">
<a href="plugins.html" data-role="button">Installed Plugins</a>
<a href="pluginCatalog.html" data-role="button" class="ui-btn-active">Plugin Catalog</a>
<a href="pluginUpdates.html" data-role="button">Automatic Updates</a>
</div>
<div id="pluginTiles"></div>
</div>
</div>
</div>
</body>
</html>

34
Html/pluginUpdates.html Normal file
View File

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<title>Plugins</title>
</head>
<body>
<div id="pluginUpdatesPage" data-role="page" class="page type-interior pluginConfigurationPage">
<div data-role="content">
<div class="content-primary">
<div data-role="controlgroup" data-type="horizontal" class="localnav" data-mini="true">
<a href="plugins.html" data-role="button">Installed Plugins</a>
<a href="pluginCatalog.html" data-role="button">Plugin Catalog</a>
<a href="pluginUpdates.html" data-role="button" class="ui-btn-active">Automatic Updates</a>
</div>
<form id="pluginUpdatesForm">
<table id="tblPluginUpdates">
<thead>
<tr>
<th></th>
<th>Automatic updates</th>
<th>Update level</th>
</tr>
</thead>
<tbody id="tbodyPluginUpdates"></tbody>
</table>
</form>
</div>
</div>
</div>
</body>
</html>

24
Html/plugins.html Normal file
View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<title>Plugins</title>
</head>
<body>
<div id="pluginsPage" data-role="page" class="page type-interior pluginConfigurationPage">
<div data-role="content">
<div class="content-primary">
<div data-role="controlgroup" data-type="horizontal" class="localnav" data-mini="true">
<a href="plugins.html" data-role="button" class="ui-btn-active">Installed Plugins</a>
<a href="pluginCatalog.html" data-role="button">Plugin Catalog</a>
<a href="pluginUpdates.html" data-role="button">Automatic Updates</a>
</div>
<div class="readOnlyContent">
<ul id="ulInstalledPlugins" data-role="listview" data-inset="true" data-auto-enhanced="false" data-split-icon="minus"></ul>
</div>
</div>
</div>
</div>
</body>
</html>

90
Html/scheduledTask.html Normal file
View File

@ -0,0 +1,90 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="scheduledTaskPage" data-role="page" class="page type-interior">
<div data-role="content">
<div class="content-primary">
<div class="readOnlyContent">
<p id="pTaskDescription"></p>
<p>
<button type="button" data-icon="plus" onclick="ScheduledTaskPage.showAddTriggerPopup();">
Add Task Trigger
</button>
</p>
<ul id="ulTaskTriggers" data-role="listview" data-inset="true" data-auto-enhanced="false" data-split-icon="minus"></ul>
</div>
</div>
</div>
<div data-role="popup" id="popupAddTrigger" class="ui-corner-all popup" style="min-width: 300px;">
<form id="addTriggerForm">
<div class="ui-corner-top ui-bar-a" style="text-align: center; padding: 0 20px;">
<h3>Add Task Trigger</h3>
</div>
<div data-role="content" class="ui-corner-bottom ui-content">
<ul data-role="listview" class="ulForm">
<li>
<label for="selectTriggerType">Trigger Type:</label>
<select id="selectTriggerType" name="selectTriggerType" onchange="ScheduledTaskPage.refreshTriggerFields(this.value);">
<option value="DailyTrigger">Daily</option>
<option value="WeeklyTrigger">Weekly</option>
<option value="IntervalTrigger">On an interval</option>
<option value="StartupTrigger">On application startup</option>
<option value="SystemEventTrigger">After a system event</option>
</select>
</li>
<li id="fldDayOfWeek">
<label for="selectDayOfWeek">Day:</label>
<select id="selectDayOfWeek" name="selectDayOfWeek">
<option value="Sunday">Sunday</option>
<option value="Monday">Monday</option>
<option value="Tuesday">Tuesday</option>
<option value="Wednesday">Wednesday</option>
<option value="Thursday">Thursday</option>
<option value="Friday">Friday</option>
<option value="Saturday">Saturday</option>
</select>
</li>
<li id="fldTimeOfDay">
<label for="txtTimeOfDay">Time:</label>
<input type="time" id="txtTimeOfDay" name="txtTimeOfDay" required="required" />
</li>
<li id="fldSelectSystemEvent">
<label for="selectSystemEvent">Event:</label>
<select id="selectSystemEvent" name="selectSystemEvent">
<option value="WakeFromSleep">Wake from sleep</option>
</select>
</li>
<li id="fldSelectInterval">
<label for="selectInterval">Every:</label>
<select id="selectInterval" name="selectInterval">
<option value="9000000000">15 minutes</option>
<option value="18000000000">30 minutes</option>
<option value="27000000000">45 minutes</option>
<option value="36000000000">1 hour</option>
<option value="72000000000">2 hours</option>
<option value="108000000000">3 hours</option>
<option value="144000000000">4 hours</option>
<option value="216000000000">6 hours</option>
<option value="288000000000">8 hours</option>
<option value="432000000000">12 hours</option>
</select>
</li>
<li>
<button type="submit" data-theme="b" data-icon="ok">
Add
</button>
<button type="button" data-icon="delete" onclick="$(this).parents('.popup').popup('close');">
Cancel
</button>
</li>
</ul>
</div>
</form>
</div>
</div>
</body>
</html>

18
Html/scheduledTasks.html Normal file
View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<title>Scheduled Tasks</title>
</head>
<body>
<div id="scheduledTasksPage" data-role="page" class="page type-interior">
<div data-role="content">
<div class="content-primary">
<div class="readOnlyContent">
<p>Below are Media Browser's scheduled tasks. Click into a task to adjust it's schedule.</p>
<ul id="ulScheduledTasks" data-role="listview" data-inset="true" data-auto-enhanced="false" data-split-icon="Play"></ul>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -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 = "<strong>";
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 += "</strong>";
$('#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("<h2>Price: $" + pkg.price.toFixed(2) + " (USD)</h2>");
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("<h3>You must be a <a href='supporter.html'>Media Browser Supporter</a> in order to register this feature.</h3>");
$('#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("<img src='" + img + "' style='max-width: 100%;border-radius:10px;-moz-box-shadow: 0 0 20px 3px " + color + ";-webkit-box-shadow: 0 0 20px 3px " + color + ";box-shadow: 0 0 20px 3px " + color + ";' />");
} else {
$('#pPreviewImage', page).hide().html("");
}
if (installedPlugin) {
$('#pCurrentVersion', page).show().html("You currently have version <strong>" + installedPlugin.Version + "</strong> 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 += '<option value="' + version.versionStr + '|' + version.classification + '">' + version.versionStr + ' (' + version.classification + ')</option>';
}
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 += '<h2 style="margin:.5em 0;">' + version.versionStr + ' (' + version.classification + ')</h2>';
html += '<div style="margin-bottom:1.5em;">' + version.description + '</div>';
}
$('#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);

View File

@ -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);

View File

@ -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 = '<div data-role="controlgroup">';
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 += '<input' + checkedAttribute + ' class="chkItemType" data-itemtype="' + type + '" type="checkbox" name="' + id + '" id="' + id + '" />';
html += '<label for="' + id + '">' + type + '</label>';
}
html += "</div>";
$('#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);

View File

@ -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 += '<p>There are no users currently connected.</p>';
$('#divConnections', page).html(html).trigger('create');
return;
}
html += '<table class="tblConnections" style="border-collapse:collapse;">';
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 += '<tr>';
html += '<td style="text-align:center;">';
html += DashboardPage.getClientType(connection);
html += '</td>';
html += '<td>';
html += user.Name;
html += '</td>';
html += '<td>';
html += connection.DeviceName;
html += '</td>';
html += '<td>';
html += DashboardPage.getNowPlayingImage(connection.NowPlayingItem);
html += '</td>';
html += '<td>';
html += DashboardPage.getNowPlayingText(connection, connection.NowPlayingItem);
html += '</td>';
html += '</tr>';
}
html += '</table>';
$('#divConnections', page).html(html);
},
getClientType: function (connection) {
if (connection.ClientType == "Dashboard") {
return "<img src='css/images/clients/html5.png' alt='Dashboard' title='Dashboard' />";
}
if (connection.ClientType == "Pc") {
return "<img src='css/images/clients/mb.png' alt='Media Browser' title='Media Browser' />";
}
if (connection.ClientType == "Android") {
return "<img src='css/images/clients/android.png' alt='Android' title='Android' />";
}
if (connection.ClientType == "Ios") {
return "<img src='css/images/clients/ios.png' alt='iOS' title='iOS' />";
}
if (connection.ClientType == "WindowsRT") {
return "<img src='css/images/clients/windowsrt.png' alt='Windows RT' title='Windows RT' />";
}
if (connection.ClientType == "WindowsPhone") {
return "<img src='css/images/clients/windowsphone.png' alt='Windows Phone' title='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 "<img class='clientNowPlayingImage' src='" + url + "' alt='" + item.Name + "' title='" + item.Name + "' />";
}
else if (item.PrimaryImageTag) {
var url = ApiClient.getImageUrl(item.Id, {
type: "Primary",
height: 100,
tag: item.PrimaryImageTag
});
return "<img class='clientNowPlayingImage' src='" + url + "' alt='" + item.Name + "' title='" + item.Name + "' />";
}
}
return "";
},
getNowPlayingText: function (connection, item) {
var html = "";
if (item) {
html += "<div>" + item.Name + "</div>";
html += "<div>";
if (item.RunTimeTicks) {
html += DashboardPage.getDisplayText(connection.NowPlayingPositionTicks || 0) + " / ";
html += DashboardPage.getDisplayText(item.RunTimeTicks);
}
html += "</div>";
}
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 += '<p>No tasks are currently running.</p>';
}
for (var i = 0, length = dashboardInfo.RunningTasks.length; i < length; i++) {
var task = dashboardInfo.RunningTasks[i];
html += '<p>';
html += task.Name;
if (task.State == "Running") {
var progress = task.CurrentProgress || { PercentComplete: 0 };
html += '<span style="color:#267F00;margin-right:5px;font-weight:bold;"> - ' + Math.round(progress.PercentComplete) + '%</span>';
html += '<button type="button" data-icon="stop" data-iconpos="notext" data-inline="true" data-theme="b" data-mini="true" onclick="DashboardPage.stopTask(\'' + task.Id + '\');">Stop</button>';
}
else if (task.State == "Cancelling") {
html += '<span style="color:#cc0000;"> - Stopping</span>';
}
html += '</p>';
}
$('#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: '<img src="css/images/notifications/error.png" class="notificationIcon" />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 += '<p><strong>A new version of ' + update.name + ' is available!</strong></p>';
html += '<button type="button" data-icon="download" data-theme="b" onclick="DashboardPage.installPluginUpdate(this);" data-name="' + update.name + '" data-version="' + update.versionStr + '" data-classification="' + update.classification + '">Update Now</button>';
}
$('#pPluginUpdates', page).html(html).trigger('create');
}).fail(function () {
Dashboard.showFooterNotification({ html: '<img src="css/images/notifications/error.png" class="notificationIcon" />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);

View File

@ -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);

View File

@ -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 += "<option value=''>None</option>";
for (var i = 0, length = allCultures.length; i < length; i++) {
var culture = allCultures[i];
html += "<option value='" + culture.ThreeLetterISOLanguageName + "'>" + culture.DisplayName + "</option>";
}
select.html(html).selectmenu("refresh");
},
populateRatings: function (allParentalRatings, page) {
var html = "";
html += "<option value=''>None</option>";
for (var i = 0, length = allParentalRatings.length; i < length; i++) {
var rating = allParentalRatings[i];
html += "<option value='" + rating.Value + "'>" + rating.Name + "</option>";
}
$('#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);

333
Html/scripts/Extensions.js Normal file
View File

@ -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 <organization> 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 <COPYRIGHT HOLDER> 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);

106
Html/scripts/IndexPage.js Normal file
View File

@ -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);

View File

@ -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 += "<img class='itemDetailImage' src='" + url + "' style='" + style + "' />";
}
$('#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('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'));
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:&nbsp;&nbsp;';
for (var i = 0, length = item.Genres.length; i < length; i++) {
if (i > 0) {
html += '&nbsp;&nbsp;/&nbsp;&nbsp;';
}
html += '<a class="interiorLink" href="#">' + item.Genres[i] + '</a>';
}
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:&nbsp;&nbsp;';
for (var i = 0, length = item.Studios.length; i < length; i++) {
if (i > 0) {
html += '&nbsp;&nbsp;/&nbsp;&nbsp;';
}
html += '<a class="interiorLink" href="#">' + item.Studios[i] + '</a>';
}
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 += "<div class='starRating emptyStarRating'></div>";
}
else if (rating < i) {
html += "<div class='starRating halfStarRating'></div>";
}
else {
html += "<div class='starRating'></div>";
}
}
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 += '<img class="galleryImage" src="' + ApiClient.getImageUrl(item.Id, {
type: "Logo",
width: downloadWidth,
tag: item.ImageTags.Logo
}) + '" />';
}
if (imageTags.Thumb) {
html += '<img class="galleryImage" src="' + ApiClient.getImageUrl(item.Id, {
type: "Thumb",
width: downloadWidth,
tag: item.ImageTags.Thumb
}) + '" />';
}
if (imageTags.Art) {
html += '<img class="galleryImage" src="' + ApiClient.getImageUrl(item.Id, {
type: "Art",
width: downloadWidth,
tag: item.ImageTags.Art
}) + '" />';
}
if (imageTags.Menu) {
html += '<img class="galleryImage" src="' + ApiClient.getImageUrl(item.Id, {
type: "Menu",
width: downloadWidth,
tag: item.ImageTags.Menu
}) + '" />';
}
if (imageTags.Disc) {
html += '<img class="galleryImage" src="' + ApiClient.getImageUrl(item.Id, {
type: "Disc",
width: downloadWidth,
tag: item.ImageTags.Disc
}) + '" />';
}
if (imageTags.Box) {
html += '<img class="galleryImage" src="' + ApiClient.getImageUrl(item.Id, {
type: "Box",
width: downloadWidth,
tag: item.ImageTags.Box
}) + '" />';
}
if (item.BackdropImageTags) {
for (var i = 0, length = item.BackdropImageTags.length; i < length; i++) {
html += '<img class="galleryImage" src="' + ApiClient.getImageUrl(item.Id, {
type: "Backdrop",
width: downloadWidth,
tag: item.BackdropImageTags[0],
index: i
}) + '" />';
}
}
$('#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);

86
Html/scripts/LogPage.js Normal file
View File

@ -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);

112
Html/scripts/LoginPage.js Normal file
View File

@ -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 += "<a id='" + linkId + "' data-userid='" + user.Id + "' data-username='" + user.Name + "' href='#popupLogin' data-rel='popup' onclick='LoginPage.authenticatingLinkId=this.id;' class='userItem'>";
} else {
html += "<a id='" + linkId + "' data-userid='" + user.Id + "' data-username='" + user.Name + "' href='#' onclick='LoginPage.authenticateUserLink(this);' class='userItem'>";
}
if (user.PrimaryImageTag) {
var imgUrl = ApiClient.getUserImageUrl(user.Id, {
width: 500,
tag: user.PrimaryImageTag,
type: "Primary"
});
html += '<img class="userItemImage" src="' + imgUrl + '" />';
} else {
html += '<img class="userItemImage" src="css/images/logindefault.png" style="background:' + background + ';" />';
}
html += '<div class="userItemContent" style="background:' + background + ';">';
html += '<div class="userItemContentInner">';
html += '<p class="userItemHeader">' + user.Name + '</p>';
html += '<p>' + LoginPage.getLastSeenText(user.LastActivityDate) + '</p>';
html += '</div>';
html += '</div>';
html += '</a>';
}
$('#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);

View File

@ -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 = '<div class="collapsibleVirtualFolder" data-role="collapsible" data-collapsed="' + isCollapsed + '" data-content-theme="c">';
html += '<h3>' + virtualFolder.Name + '</h3>';
html += '<ul class="mediaFolderLocations" data-inset="true" data-role="listview" data-split-icon="minus">';
html += '<li data-role="list-divider" class="mediaLocationsHeader">Media Locations';
html += '<button type="button" data-icon="plus" data-mini="true" data-theme="c" data-inline="true" data-iconpos="notext" onclick="MediaLibraryPage.addMediaLocation(' + index + ');"></button>';
html += '</li>';
for (var i = 0, length = virtualFolder.Locations.length; i < length; i++) {
var location = virtualFolder.Locations[i];
html += '<li>';
html += '<a class="lnkMediaLocation" href="#">' + location + '</a>';
html += '<a href="#" data-index="' + i + '" data-folderindex="' + index + '" onclick="MediaLibraryPage.deleteMediaLocation(this);"></a>';
html += '</li>';
}
html += '</ul>';
html += '<p>';
html += '<button type="button" data-inline="true" data-icon="minus" data-folderindex="' + index + '" onclick="MediaLibraryPage.deleteVirtualFolder(this);">Remove collection</button>';
html += '<button type="button" data-inline="true" data-icon="pencil" data-folderindex="' + index + '" onclick="MediaLibraryPage.renameVirtualFolder(this);">Rename collection</button>';
html += '</p>';
html += '</div>';
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 += "<br/><br/>The following media locations will be removed from your library:<br/><br/>";
msg += locations.join("<br/>");
}
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);

170
Html/scripts/MediaPlayer.js Normal file
View File

@ -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 += '<audio class="itemAudio" preload="none" controls autoplay>';
html += '<source type="audio/mpeg" src="' + mp3Url + '">';
html += '<source type="audio/aac" src="' + aacUrl + '">';
html += '<source type="audio/webm" src="' + webmUrl + '">';
html += '<source type="audio/ogg" src="' + oggUrl + '">';
html += '</audio';
var nowPlayingBar = $('#nowPlayingBar').show();
$('#mediaElement', nowPlayingBar).html(html);
return $('audio', nowPlayingBar)[0];
},
playVideo: function (items) {
var item = items[0];
var screenWidth = Math.max(screen.height, screen.width);
var screenHeight = Math.min(screen.height, screen.width);
var baseParams = {
id: item.Id,
audioChannels: 2,
audioBitrate: 128000,
videoBitrate: 500000,
maxWidth: screenWidth,
maxHeight: screenHeight
};
var tsVideoUrl = ApiClient.getUrl('video.ts', $.extend({}, baseParams, {
videoCodec: 'h264',
audioCodec: 'aac'
}));
var webmVideoUrl = ApiClient.getUrl('video.webm', $.extend({}, baseParams, {
videoCodec: 'vpx',
audioCodec: 'Vorbis'
}));
var ogvVideoUrl = ApiClient.getUrl('video.ogv', $.extend({}, baseParams, {
videoCodec: 'theora',
audioCodec: 'Vorbis'
}));
var html = '';
html += '<video class="itemVideo" preload="none" controls autoplay>';
html += '<source type=\'video/mp2t; codecs="h264, aac"\' src="' + tsVideoUrl + '">';
html += '<source type=\'video/webm; codecs="vp8, vorbis"\' src="' + webmVideoUrl + '">';
html += '<source type=\'video/ogg; codecs="theora, vorbis"\' src="' + ogvVideoUrl + '">';
html += '</video';
var nowPlayingBar = $('#nowPlayingBar').show();
$('#mediaElement', nowPlayingBar).html(html);
return $('video', nowPlayingBar)[0];
},
stop: function () {
var elem = MediaPlayer.mediaElement;
elem.pause();
elem.src = "";
$(elem).remove();
$('#nowPlayingBar').hide();
MediaPlayer.mediaElement = null;
},
isPlaying: function() {
return MediaPlayer.mediaElement;
}
};

View File

@ -0,0 +1,103 @@
var MetadataConfigurationPage = {
onPageShow: function () {
Dashboard.showLoadingMsg();
var page = this;
var config;
var allCultures;
var allCountries;
ApiClient.getServerConfiguration().done(function (result) {
config = result;
MetadataConfigurationPage.load(page, config, allCultures, allCountries);
});
ApiClient.getCultures().done(function (result) {
MetadataConfigurationPage.populateLanguages(result);
allCultures = result;
MetadataConfigurationPage.load(page, config, allCultures, allCountries);
});
ApiClient.getCountries().done(function (result) {
MetadataConfigurationPage.populateCountries(result);
allCountries = result;
MetadataConfigurationPage.load(page, config, allCultures, allCountries);
});
},
load: function (page, config, allCultures, allCountries) {
if (!config || !allCultures || !allCountries) {
return;
}
$('#chkEnableInternetProviders', page).checked(config.EnableInternetProviders).checkboxradio("refresh");
$('#chkSaveLocal', page).checked(config.SaveLocalMeta).checkboxradio("refresh");
$('#txtRefreshDays', page).val(config.MetadataRefreshDays);
$('#selectLanguage', page).val(config.PreferredMetadataLanguage).selectmenu("refresh");
$('#selectCountry', page).val(config.MetadataCountryCode).selectmenu("refresh");
Dashboard.hideLoadingMsg();
},
populateCountries: function (allCountries) {
var html = "";
html += "<option value=''>None</option>";
for (var i = 0, length = allCountries.length; i < length; i++) {
var culture = allCountries[i];
html += "<option value='" + culture.TwoLetterISORegionName + "'>" + culture.DisplayName + "</option>";
}
$('#selectCountry', '#metadataConfigurationPage').html(html).selectmenu("refresh");
},
populateLanguages: function (allCultures) {
var html = "";
html += "<option value=''>None</option>";
for (var i = 0, length = allCultures.length; i < length; i++) {
var culture = allCultures[i];
html += "<option value='" + culture.TwoLetterISOLanguageName + "'>" + culture.DisplayName + "</option>";
}
$('#selectLanguage', '#metadataConfigurationPage').html(html).selectmenu("refresh");
},
onSubmit: function () {
Dashboard.showLoadingMsg();
var form = this;
ApiClient.getServerConfiguration().done(function (config) {
config.EnableInternetProviders = $('#chkEnableInternetProviders', form).checked();
config.SaveLocalMeta = $('#chkSaveLocal', form).checked();
config.MetadataRefreshDays = $('#txtRefreshDays', form).val();
config.PreferredMetadataLanguage = $('#selectLanguage', form).val();
config.MetadataCountryCode = $('#selectCountry', form).val();
ApiClient.updateServerConfiguration(config).done(Dashboard.processServerConfigurationUpdateResult);
});
// Disable default form submission
return false;
}
};
$(document).on('pageshow', "#metadataConfigurationPage", MetadataConfigurationPage.onPageShow);

View File

@ -0,0 +1,74 @@
var MetadataImagesPage = {
onPageShow: function () {
Dashboard.showLoadingMsg();
var page = this;
ApiClient.getServerConfiguration().done(function(result) {
MetadataImagesPage.load(page, result);
});
},
load: function (page, config) {
$('#selectTmdbPersonImageDownloadSize', page).val(config.TmdbFetchedProfileSize).selectmenu("refresh");
$('#selectTmdbPosterDownloadSize', page).val(config.TmdbFetchedPosterSize).selectmenu("refresh");
$('#selectTmdbBackdropDownloadSize', page).val(config.TmdbFetchedBackdropSize).selectmenu("refresh");
$('#chkRefreshItemImages', page).checked(config.RefreshItemImages).checkboxradio("refresh");
$('#txtNumbackdrops', page).val(config.MaxBackdrops);
$('#chkDownloadMovieArt', page).checked(config.DownloadMovieArt).checkboxradio("refresh");
$('#chkDownloadMovieBanner', page).checked(config.DownloadMovieBanner).checkboxradio("refresh");
$('#chkDownloadMovieDisc', page).checked(config.DownloadMovieDisc).checkboxradio("refresh");
$('#chkDownloadMovieLogo', page).checked(config.DownloadMovieLogo).checkboxradio("refresh");
$('#chkDownloadMovieThumb', page).checked(config.DownloadMovieThumb).checkboxradio("refresh");
$('#chKDownloadTVArt', page).checked(config.DownloadTVArt).checkboxradio("refresh");
$('#chkDownloadTVBanner', page).checked(config.DownloadTVBanner).checkboxradio("refresh");
$('#chkDownloadTVLogo', page).checked(config.DownloadTVLogo).checkboxradio("refresh");
$('#chkDownloadTVThumb', page).checked(config.DownloadTVThumb).checkboxradio("refresh");
$('#chkDownloadSeasonBanner', page).checked(config.DownloadTVSeasonBanner).checkboxradio("refresh");
$('#chkDownloadSeasonThumb', page).checked(config.DownloadTVSeasonThumb).checkboxradio("refresh");
$('#chkDownloadSeasonBackdrops', page).checked(config.DownloadTVSeasonBackdrops).checkboxradio("refresh");
Dashboard.hideLoadingMsg();
},
onSubmit: function () {
Dashboard.showLoadingMsg();
var form = this;
ApiClient.getServerConfiguration().done(function (config) {
config.TmdbFetchedProfileSize = $('#selectTmdbPersonImageDownloadSize', form).val();
config.TmdbFetchedPosterSize = $('#selectTmdbPosterDownloadSize', form).val();
config.TmdbFetchedBackdropSize = $('#selectTmdbBackdropDownloadSize', form).val();
config.RefreshItemImages = $('#chkRefreshItemImages', form).checked();
config.MaxBackdrops = $('#txtNumbackdrops', form).val();
config.DownloadMovieArt = $('#chkDownloadMovieArt', form).checked();
config.DownloadMovieBanner = $('#chkDownloadMovieBanner', form).checked();
config.DownloadMovieDisc = $('#chkDownloadMovieDisc', form).checked();
config.DownloadMovieLogo = $('#chkDownloadMovieLogo', form).checked();
config.DownloadMovieThumb = $('#chkDownloadMovieThumb', form).checked();
config.DownloadTVArt = $('#chKDownloadTVArt', form).checked();
config.DownloadTVBanner = $('#chkDownloadTVBanner', form).checked();
config.DownloadTVLogo = $('#chkDownloadTVLogo', form).checked();
config.DownloadTVThumb = $('#chkDownloadTVThumb', form).checked();
config.DownloadTVSeasonBanner = $('#chkDownloadSeasonBanner', form).checked();
config.DownloadTVSeasonThumb = $('#chkDownloadSeasonThumb', form).checked();
config.DownloadTVSeasonBackdrops = $('#chkDownloadSeasonBackdrops', form).checked();
ApiClient.updateServerConfiguration(config).done(Dashboard.processServerConfigurationUpdateResult);
});
// Disable default form submission
return false;
}
};
$(document).on('pageshow', "#metadataImagesConfigurationPage", MetadataImagesPage.onPageShow);

View File

@ -0,0 +1,80 @@
var PluginCatalogPage = {
onPageShow: function () {
PluginCatalogPage.reloadList();
},
reloadList: function () {
Dashboard.showLoadingMsg();
var promise1 = ApiClient.getAvailablePlugins();
var promise2 = ApiClient.getInstalledPlugins();
$.when(promise1, promise2).done(function (response1, response2) {
PluginCatalogPage.populateList(response1[0], response2[0]);
});
},
populateList: function (availablePlugins, installedPlugins) {
var page = $($.mobile.activePage);
availablePlugins = availablePlugins.filter(function (p) {
return p.type == "UserInstalled";
}).sort(function (a, b) {
return a.name > b.name ? 1 : -1;
});
var html = "";
for (var i = 0, length = availablePlugins.length; i < length; i++) {
var plugin = availablePlugins[i];
html += "<div class='posterViewItem'><a href='addPlugin.html?name=" + encodeURIComponent(plugin.name) + "'>";
if (plugin.thumbImage) {
html += "<img src='" + plugin.thumbImage + "' />";
} else {
html += "<img style='background:#444444;' src='css/images/defaultCollectionImage.png' />";
}
if (plugin.isPremium) {
html += "<div class='premiumBanner'><img src='css/images/premiumflag.png' /></div>";
}
var color = plugin.tileColor || Dashboard.getRandomMetroColor();
html += "<div class='posterViewItemText' style='background:" + color + "'>";
var installedPlugin = installedPlugins.filter(function (ip) {
return ip.Name == plugin.name;
})[0];
if (installedPlugin) {
html += plugin.name + " (Installed)";
} else {
html += plugin.name;
}
html += "</div>";
html += "</a></div>";
}
$('#pluginTiles', page).html(html);
Dashboard.hideLoadingMsg();
}
};
$(document).on('pageshow', "#pluginCatalogPage", PluginCatalogPage.onPageShow);

View File

@ -0,0 +1,109 @@
var PluginUpdatesPage = {
onPageShow: function () {
Dashboard.showLoadingMsg();
$('.liPluginUpdate', this).remove();
ApiClient.getInstalledPlugins().done(PluginUpdatesPage.loadPlugins);
},
loadPlugins: function (plugins) {
plugins = plugins.filter(function (p) {
return !p.IsCorePlugin;
});
var elem = $('#tbodyPluginUpdates', $.mobile.activePage).html('');
for (var i = 0, length = plugins.length; i < length; i++) {
PluginUpdatesPage.addPlugin(plugins[i], i, elem);
}
Dashboard.hideLoadingMsg();
},
addPlugin: function (plugin, fieldIndex, elem) {
var html = "";
html += "<tr>";
html += "<td><h3>" + plugin.Name + "</h3></td>";
var fieldId = "liPluginUpdateFielda" + fieldIndex;
var options = PluginUpdatesPage.getHtmlOptions(["Off", "On"], (plugin.EnableAutoUpdate ? "On" : "Off"));
html += "<td>";
html += "<select data-uniqueid='" + plugin.UniqueId + "' onchange='PluginUpdatesPage.setAutoUpdate(this);' data-role='slider' id='" + fieldId + "' name='" + fieldId + "'>" + options + "</select>";
html += "</td>";
fieldId = "liPluginUpdateFieldb" + fieldIndex;
options = PluginUpdatesPage.getHtmlOptions(["Release", "Beta", "Dev"], plugin.UpdateClass);
html += "<td>";
html += "<select data-uniqueid='" + plugin.UniqueId + "' onchange='PluginUpdatesPage.setUpdateClass(this);' data-inline='true' id='" + fieldId + "' name='" + fieldId + "'>" + options + "</select>";
html += "</td>";
html += "</tr>";
elem.append(html).trigger('create');
},
getHtmlOptions: function (names, selectedValue) {
var html = "";
for (var i = 0, length = names.length; i < length; i++) {
var name = names[i];
if (name == selectedValue) {
html += '<option value="' + name + '" selected="selected">' + name + '</option>';
} else {
html += '<option value="' + name + '">' + name + '</option>';
}
}
return html;
},
setAutoUpdate: function (select) {
var id = $(select).attr('data-uniqueid');
Dashboard.showLoadingMsg();
ApiClient.getPluginConfiguration(id).done(function (config) {
config.EnableAutoUpdate = select.selectedIndex === 1;
ApiClient.updatePluginConfiguration(id, config).done(Dashboard.hideLoadingMsg);
});
},
setUpdateClass: function (select) {
var id = $(select).attr('data-uniqueid');
Dashboard.showLoadingMsg();
ApiClient.getPluginConfiguration(id).done(function (config) {
config.UpdateClass = select.value;
ApiClient.updatePluginConfiguration(id, config).done(Dashboard.hideLoadingMsg);
});
}
};
$(document).on('pageshow', "#pluginUpdatesPage", PluginUpdatesPage.onPageShow);

View File

@ -0,0 +1,92 @@
var PluginsPage = {
onPageShow: function () {
PluginsPage.reloadList();
},
reloadList: function () {
Dashboard.showLoadingMsg();
var promise1 = ApiClient.getInstalledPlugins();
var promise2 = $.getJSON("configurationpages?pageType=PluginConfiguration");
$.when(promise1, promise2).done(function(response1, response2) {
PluginsPage.populateList(response1[0], response2[0]);
});
},
populateList: function (plugins, pluginConfigurationPages) {
var page = $($.mobile.activePage);
plugins = plugins.sort(function (plugin1, plugin2) {
return (plugin1.IsCorePlugin.toString() + plugin1.Name) > (plugin2.IsCorePlugin.toString() + plugin2.Name) ? 1 : -1;
});
var html = "";
for (var i = 0, length = plugins.length; i < length; i++) {
var plugin = plugins[i];
if (plugin.IsCorePlugin) {
continue;
}
var configPage = $.grep(pluginConfigurationPages, function (pluginConfigurationPage) {
return pluginConfigurationPage.OwnerPluginName == plugin.Name;
})[0];
html += "<li>";
var href = configPage ? Dashboard.getConfigurationPageUrl(configPage.Name) : "#";
html += "<a href='" + href + "'>";
html += "<h3>" + plugin.Name + "</h3>";
html += "<p><strong>" + plugin.Version + "</strong></p>";
html += "</a>";
if (!plugin.IsCorePlugin) {
html += "<a data-uniqueid='" + plugin.UniqueId + "' data-pluginname='" + plugin.Name + "' onclick='PluginsPage.deletePlugin(this);' href='#'>Delete</a>";
}
html += "</li>";
}
$('#ulInstalledPlugins', page).html(html).listview('refresh');
Dashboard.hideLoadingMsg();
},
deletePlugin: function (link) {
var name = link.getAttribute('data-pluginname');
var uniqueid = link.getAttribute('data-uniqueid');
var msg = "Are you sure you wish to uninstall " + name + "?";
Dashboard.confirm(msg, "Uninstall Plugin", function (result) {
if (result) {
Dashboard.showLoadingMsg();
ApiClient.uninstallPlugin(uniqueid).done(function () {
PluginsPage.reloadList();
});
}
});
}
};
$(document).on('pageshow', "#pluginsPage", PluginsPage.onPageShow);

View File

@ -0,0 +1,294 @@
var ScheduledTaskPage = {
onPageShow: function () {
ScheduledTaskPage.refreshScheduledTask();
},
refreshScheduledTask: function () {
Dashboard.showLoadingMsg();
var id = getParameterByName('id');
ApiClient.getScheduledTask(id).done(ScheduledTaskPage.loadScheduledTask);
},
loadScheduledTask: function (task) {
Dashboard.setPageTitle(task.Name);
$('#pTaskDescription', $.mobile.activePage).html(task.Description);
ScheduledTaskPage.loadTaskTriggers(task);
Dashboard.hideLoadingMsg();
},
loadTaskTriggers: function (task) {
var html = '';
html += '<li data-role="list-divider"><h3>Task Triggers</h3></li>';
for (var i = 0, length = task.Triggers.length; i < length; i++) {
var trigger = task.Triggers[i];
html += '<li>';
html += '<a href="#">';
html += ScheduledTaskPage.getTriggerFriendlyName(trigger);
html += '</a>';
html += '<a href="#" onclick="ScheduledTaskPage.confirmDeleteTrigger(' + i + ');">Delete</a>';
html += '</li>';
}
$('#ulTaskTriggers', $.mobile.activePage).html(html).listview('refresh');
},
getTriggerFriendlyName: function (trigger) {
if (trigger.Type == 'DailyTrigger') {
return 'Daily at ' + ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks);
}
if (trigger.Type == 'WeeklyTrigger') {
return trigger.DayOfWeek + 's at ' + ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks);
}
if (trigger.Type == 'SystemEventTrigger') {
if (trigger.SystemEvent == 'WakeFromSleep') {
return 'On wake from sleep';
}
}
if (trigger.Type == 'IntervalTrigger') {
var hours = trigger.IntervalTicks / 36000000000;
if (hours == .25) {
return "Every 15 minutes";
}
if (hours == .5) {
return "Every 30 minutes";
}
if (hours == .75) {
return "Every 45 minutes";
}
if (hours == 1) {
return "Every hour";
}
return 'Every ' + hours + ' hours';
}
if (trigger.Type == 'StartupTrigger') {
return 'On application startup';
}
return trigger.Type;
},
getDisplayTime: function (ticks) {
var hours = ticks / 36000000000;
if (hours < 1) {
hours = 0;
}
hours = parseInt(hours);
ticks -= (hours * 36000000000);
var minutes = parseInt(ticks / 600000000);
var suffix = "am";
if (hours > 11) {
suffix = "pm";
}
hours = hours % 12;
if (hours == 0) {
hours = 12;
}
if (minutes < 10) {
minutes = '0' + minutes;
}
return hours + ':' + minutes + ' ' + suffix;
},
showAddTriggerPopup: function () {
var page = $.mobile.activePage;
$('#selectTriggerType', page).val('DailyTrigger').trigger('change').selectmenu('refresh');
$('#popupAddTrigger', page).popup("open").on("popupafterclose", function () {
$('#addTriggerForm', page).off("submit");
$(this).off("popupafterclose");
});
$('#addTriggerForm', page).on('submit', function () {
ScheduledTaskPage.addTrigger();
return false;
});
},
addTrigger: function () {
Dashboard.showLoadingMsg();
var id = getParameterByName('id');
ApiClient.getScheduledTask(id).done(function (task) {
task.Triggers.push(ScheduledTaskPage.getTriggerToAdd());
ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).done(function () {
$('#popupAddTrigger').popup('close');
ScheduledTaskPage.refreshScheduledTask();
});
});
},
confirmDeleteTrigger: function (index) {
Dashboard.confirm("Are you sure you wish to delete this task trigger?", "Delete Task Trigger", function (result) {
if (result) {
ScheduledTaskPage.deleteTrigger(index);
}
});
},
deleteTrigger: function (index) {
Dashboard.showLoadingMsg();
var id = getParameterByName('id');
ApiClient.getScheduledTask(id).done(function (task) {
task.Triggers.remove(index);
ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).done(function () {
ScheduledTaskPage.refreshScheduledTask();
});
});
},
refreshTriggerFields: function (triggerType) {
var page = $.mobile.activePage;
if (triggerType == 'DailyTrigger') {
$('#fldTimeOfDay', page).show();
$('#fldDayOfWeek', page).hide();
$('#fldSelectSystemEvent', page).hide();
$('#fldSelectInterval', page).hide();
$('#txtTimeOfDay', page).attr('required', 'required');
}
else if (triggerType == 'WeeklyTrigger') {
$('#fldTimeOfDay', page).show();
$('#fldDayOfWeek', page).show();
$('#fldSelectSystemEvent', page).hide();
$('#fldSelectInterval', page).hide();
$('#txtTimeOfDay', page).attr('required', 'required');
}
else if (triggerType == 'SystemEventTrigger') {
$('#fldTimeOfDay', page).hide();
$('#fldDayOfWeek', page).hide();
$('#fldSelectSystemEvent', page).show();
$('#fldSelectInterval', page).hide();
$('#txtTimeOfDay', page).removeAttr('required');
}
else if (triggerType == 'IntervalTrigger') {
$('#fldTimeOfDay', page).hide();
$('#fldDayOfWeek', page).hide();
$('#fldSelectSystemEvent', page).hide();
$('#fldSelectInterval', page).show();
$('#txtTimeOfDay', page).removeAttr('required');
}
else if (triggerType == 'StartupTrigger') {
$('#fldTimeOfDay', page).hide();
$('#fldDayOfWeek', page).hide();
$('#fldSelectSystemEvent', page).hide();
$('#fldSelectInterval', page).hide();
$('#txtTimeOfDay', page).removeAttr('required');
}
},
getTriggerToAdd: function () {
var page = $.mobile.activePage;
var trigger = {
Type: $('#selectTriggerType', page).val()
};
if (trigger.Type == 'DailyTrigger') {
trigger.TimeOfDayTicks = ScheduledTaskPage.getTimeOfDayTicks($('#txtTimeOfDay', page).val());
}
else if (trigger.Type == 'WeeklyTrigger') {
trigger.DayOfWeek = $('#selectDayOfWeek', page).val();
trigger.TimeOfDayTicks = ScheduledTaskPage.getTimeOfDayTicks($('#txtTimeOfDay', page).val());
}
else if (trigger.Type == 'SystemEventTrigger') {
trigger.SystemEvent = $('#selectSystemEvent', page).val();
}
else if (trigger.Type == 'IntervalTrigger') {
trigger.IntervalTicks = $('#selectInterval', page).val();
}
return trigger;
},
getTimeOfDayTicks: function (val) {
var vals = val.split(':');
var hours = vals[0];
var minutes = vals[1];
// Add hours
var ticks = hours * 60 * 60 * 1000 * 10000;
ticks += minutes * 60 * 1000 * 10000;
return ticks;
}
};
$(document).on('pageshow', "#scheduledTaskPage", ScheduledTaskPage.onPageShow);

View File

@ -0,0 +1,170 @@
var ScheduledTasksPage = {
onPageShow: function () {
Dashboard.showLoadingMsg();
ScheduledTasksPage.reloadList(true);
$(document).on("websocketmessage", ScheduledTasksPage.onWebSocketMessage).on("websocketopen", ScheduledTasksPage.onWebSocketConnectionChange).on("websocketerror", ScheduledTasksPage.onWebSocketConnectionChange).on("websocketclose", ScheduledTasksPage.onWebSocketConnectionChange);
},
onPageHide: function () {
$(document).off("websocketmessage", ScheduledTasksPage.onWebSocketMessage).off("websocketopen", ScheduledTasksPage.onWebSocketConnectionChange).off("websocketerror", ScheduledTasksPage.onWebSocketConnectionChange).off("websocketclose", ScheduledTasksPage.onWebSocketConnectionChange);
ScheduledTasksPage.stopInterval();
},
startInterval: function () {
if (Dashboard.isWebSocketOpen()) {
Dashboard.sendWebSocketMessage("ScheduledTasksInfoStart", "1500,1500");
}
},
stopInterval: function () {
if (Dashboard.isWebSocketOpen()) {
Dashboard.sendWebSocketMessage("ScheduledTasksInfoStop");
}
},
onWebSocketMessage: function (e, msg) {
if (msg.MessageType == "ScheduledTasksInfo") {
ScheduledTasksPage.populateList(msg.Data);
}
},
onWebSocketConnectionChange: function() {
ScheduledTasksPage.reloadList(true);
},
reloadList: function (updateInterval) {
if (updateInterval) {
ScheduledTasksPage.stopInterval();
}
ApiClient.getScheduledTasks().done(function (tasks) {
ScheduledTasksPage.populateList(tasks);
Dashboard.hideLoadingMsg();
if (updateInterval) {
ScheduledTasksPage.startInterval();
}
});
},
populateList: function (tasks) {
tasks = tasks.sort(function (a, b) {
a = a.Category + " " + a.Name;
b = b.Category + " " + b.Name;
if (a == b) {
return 0;
}
if (a < b) {
return -1;
}
return 1;
});
var page = $($.mobile.activePage);
var html = "";
var currentCategory;
for (var i = 0, length = tasks.length; i < length; i++) {
var task = tasks[i];
if (task.Category != currentCategory) {
currentCategory = task.Category;
html += "<li data-role='list-divider'>" + currentCategory + "</li>";
}
html += "<li>";
html += "<a href='scheduledTask.html?id=" + task.Id + "'>";
html += "<h3>" + task.Name + "</h3>";
if (task.State == "Idle") {
if (task.LastExecutionResult) {
var text = "Last run " + humane_date(task.LastExecutionResult.EndTimeUtc) + ', taking ' + humane_elapsed(task.LastExecutionResult.StartTimeUtc, task.LastExecutionResult.EndTimeUtc);
if (task.LastExecutionResult.Status == "Failed") {
text += " <span style='color:#FF0000;'>(failed)</span>";
}
else if (task.LastExecutionResult.Status == "Cancelled") {
text += " <span style='color:#0026FF;'>(cancelled)</span>";
}
else if (task.LastExecutionResult.Status == "Aborted") {
text += " <span style='color:#FF0000;'>(Aborted by server shutdown)</span>";
}
html += "<p>" + text + "</p>";
}
html += "<a href='#' data-icon='play' onclick='ScheduledTasksPage.startTask(\"" + task.Id + "\");'>Start</a>";
}
else if (task.State == "Running") {
var progress = task.CurrentProgress || { PercentComplete: 0 };
progress = Math.round(progress.PercentComplete);
html += '<p><progress max="100" value="' + progress + '" title="' + progress + '%">';
html += '' + progress + '%';
html += '</progress>';
html += "<span style='color:#009F00;margin-left:5px;'>" + progress + "%</span>";
html += '</p>';
html += "<a href='#' data-icon='stop' onclick='ScheduledTasksPage.stopTask(\"" + task.Id + "\");'>Stop</a>";
} else {
html += "<p style='color:#FF0000;'>Stopping</p>";
html += "<a href='#' data-icon='play' style='visibility:hidden;'>Start</a>";
}
html += "</a>";
html += "</li>";
}
$('#ulScheduledTasks', page).html(html).listview('refresh');
},
startTask: function (id) {
Dashboard.showLoadingMsg();
ApiClient.startScheduledTask(id).done(function (result) {
ScheduledTasksPage.reloadList();
});
},
stopTask: function (id) {
Dashboard.showLoadingMsg();
ApiClient.stopScheduledTask(id).done(function (result) {
ScheduledTasksPage.reloadList();
});
}
};
$(document).on('pageshow', "#scheduledTasksPage", ScheduledTasksPage.onPageShow).on('pagehide', "#scheduledTasksPage", ScheduledTasksPage.onPageHide);

View File

@ -0,0 +1,79 @@
var SupporterKeyPage = {
onPageShow: function () {
SupporterKeyPage.load();
},
onPageHide: function () {
},
load: function() {
Dashboard.showLoadingMsg();
var page = $.mobile.activePage;
ApiClient.getPluginSecurityInfo().done(function (info) {
$('#txtSupporterKey', page).val(info.SupporterKey);
$('#txtLegacyKey', page).val(info.LegacyKey);
if (info.IsMBSupporter) {
$('.supporterOnly', page).show();
} else {
$('.supporterOnly', page).hide();
}
Dashboard.hideLoadingMsg();
});
},
updateSupporterKey: function () {
Dashboard.showLoadingMsg();
var page = $.mobile.activePage;
var key = $('#txtSupporterKey', page).val();
var legacyKey = $('#txtLegacyKey', page).val();
var info = {
SupporterKey: key,
LegacyKey: legacyKey
};
var url = ApiClient.getUrl("Plugins/SecurityInfo");
console.log(url);
$.post(url, JSON.stringify(info)).done(function () {
Dashboard.resetPluginSecurityInfo();
Dashboard.hideLoadingMsg();
SupporterPage.load();
});
return false;
},
retrieveSupporterKey: function () {
Dashboard.showLoadingMsg();
var page = $.mobile.activePage;
var email = $('#txtEmail', page).val();
var url = "http://mb3admin.com/admin/service/supporter/retrievekey?email="+email;
console.log(url);
$.post(url).done(function (res) {
var result = JSON.parse(res);
Dashboard.hideLoadingMsg();
if (result.Success) {
Dashboard.alert("Key emailed to "+email);
} else {
Dashboard.showError(result.ErrorMessage);
}
console.log(result);
});
return false;
}
};
$(document).on('pageshow', "#supporterKeyPage", SupporterKeyPage.onPageShow)
.on('pagehide', "#supporterKeyPage", SupporterKeyPage.onPageHide);

View File

@ -0,0 +1,29 @@
var SupporterPage = {
onPageShow: function () {
SupporterPage.load();
},
onPageHide: function () {
},
load: function() {
Dashboard.showLoadingMsg();
var page = $.mobile.activePage;
ApiClient.getPluginSecurityInfo().done(function (info) {
$('#txtSupporterKey', page).val(info.SupporterKey);
if (info.IsMBSupporter) {
$('.supporterOnly', page).show();
} else {
$('.supporterOnly', page).hide();
}
$('#paypalReturnUrl', page).val(ApiClient.getCustomUrl("dashboard/supporterKey.html"));
Dashboard.hideLoadingMsg();
});
}
};
$(document).on('pageshow', "#supporterPage", SupporterPage.onPageShow)
.on('pagehide', "#supporterPage", SupporterPage.onPageHide);

View File

@ -0,0 +1,88 @@
var UpdatePasswordPage = {
onPageShow: function () {
UpdatePasswordPage.loadUser();
},
loadUser: function() {
var page = $.mobile.activePage;
var userid = getParameterByName("userId");
ApiClient.getUser(userid).done(function (user) {
Dashboard.setPageTitle(user.Name);
if (user.HasPassword) {
$('#btnResetPassword', page).show();
} else {
$('#btnResetPassword', page).hide();
}
});
$('#txtCurrentPassword', page).val('');
$('#txtNewPassword', page).val('');
$('#txtNewPasswordConfirm', page).val('');
},
save: function () {
var userId = getParameterByName("userId");
var page = $($.mobile.activePage);
var currentPassword = $('#txtCurrentPassword', page).val();
var newPassword = $('#txtNewPassword', page).val();
ApiClient.updateUserPassword(userId, currentPassword, newPassword).done(UpdatePasswordPage.saveComplete);
},
saveComplete: function () {
Dashboard.hideLoadingMsg();
Dashboard.alert("Password saved.");
UpdatePasswordPage.loadUser();
},
resetPassword: function () {
var msg = "Are you sure you wish to reset the password?";
Dashboard.confirm(msg, "Password Reset", function (result) {
if (result) {
var userId = getParameterByName("userId");
Dashboard.showLoadingMsg();
ApiClient.resetUserPassword(userId).done(function () {
Dashboard.hideLoadingMsg();
Dashboard.alert("The password has been reset.");
UpdatePasswordPage.loadUser();
});
}
});
},
onSubmit: function () {
var page = $($.mobile.activePage);
if ($('#txtNewPassword', page).val() != $('#txtNewPasswordConfirm', page).val()) {
Dashboard.showError("Password and password confirmation must match.");
return false;
}
Dashboard.showLoadingMsg();
UpdatePasswordPage.save();
// Disable default form submission
return false;
}
};
$(document).on('pageshow', "#updatePasswordPage", UpdatePasswordPage.onPageShow);

View File

@ -0,0 +1,181 @@
var UserImagePage = {
onPageShow: function () {
UserImagePage.reloadUser();
$("#userImageDropZone", this).on('dragover', UserImagePage.onImageDragOver).on('drop', UserImagePage.onImageDrop);
},
onPageHide: function () {
$("#userImageDropZone", this).off('dragover', UserImagePage.onImageDragOver).off('drop', UserImagePage.onImageDrop);
},
reloadUser: function () {
var userId = getParameterByName("userId");
Dashboard.showLoadingMsg();
ApiClient.getUser(userId).done(function (user) {
var page = $($.mobile.activePage);
$('#uploadUserImage', page).val('').trigger('change');
Dashboard.setPageTitle(user.Name);
if (user.PrimaryImageTag) {
var imageUrl = ApiClient.getUserImageUrl(user.Id, {
height: 450,
tag: user.PrimaryImageTag,
type: "Primary"
});
$('#fldImage', page).show().html('').html("<img height='200px' src='" + imageUrl + "' />");
$('#fldDeleteImage', page).show();
$('#headerUploadNewImage', page).show();
} else {
$('#fldImage', page).hide().html('');
$('#fldDeleteImage', page).hide();
$('#headerUploadNewImage', page).hide();
}
Dashboard.hideLoadingMsg();
});
},
deleteImage: function () {
Dashboard.confirm("Are you sure you wish to delete the image?", "Delete Image", function (result) {
if (result) {
Dashboard.showLoadingMsg();
var userId = getParameterByName("userId");
ApiClient.deleteUserImage(userId, "primary").done(UserImagePage.processImageChangeResult);
}
});
},
processImageChangeResult: function () {
Dashboard.hideLoadingMsg();
Dashboard.validateCurrentUser();
UserImagePage.reloadUser();
},
onFileUploadChange: function (fileUpload) {
UserImagePage.setFiles(fileUpload.files);
},
setFiles: function (files) {
var page = $.mobile.activePage;
var file = files[0];
if (!file || !file.type.match('image.*')) {
$('#userImageOutput', page).html('');
$('#fldUpload', page).hide();
UserImagePage.currentFile = null;
return;
}
UserImagePage.currentFile = file;
var reader = new FileReader();
reader.onerror = UserImagePage.onFileReaderError;
reader.onloadstart = UserImagePage.onFileReaderOnloadStart;
reader.onabort = UserImagePage.onFileReaderAbort;
// Closure to capture the file information.
reader.onload = (function (theFile) {
return function (e) {
// Render thumbnail.
var html = ['<img style="max-width:500px;max-height:200px;" src="', e.target.result, '" title="', escape(theFile.name), '"/>'].join('');
$('#userImageOutput', page).html(html);
$('#fldUpload', page).show();
};
})(file);
// Read in the image file as a data URL.
reader.readAsDataURL(file);
},
onFileReaderError: function (evt) {
Dashboard.hideLoadingMsg();
switch (evt.target.error.code) {
case evt.target.error.NOT_FOUND_ERR:
Dashboard.showError('File Not Found!');
break;
case evt.target.error.NOT_READABLE_ERR:
Dashboard.showError('File is not readable');
break;
case evt.target.error.ABORT_ERR:
break; // noop
default:
Dashboard.showError('An error occurred reading this file.');
};
},
onFileReaderOnloadStart: function (evt) {
$('#fldUpload', $.mobile.activePage).hide();
},
onFileReaderAbort: function (evt) {
Dashboard.hideLoadingMsg();
Dashboard.showError('File read cancelled');
},
onSubmit: function () {
var file = UserImagePage.currentFile;
if (!file || !file.type.match('image.*')) {
return false;
}
Dashboard.showLoadingMsg();
var userId = getParameterByName("userId");
ApiClient.uploadUserImage(userId, 'Primary', file).done(UserImagePage.processImageChangeResult);
return false;
},
onImageDrop: function (e) {
e.preventDefault();
UserImagePage.setFiles(e.originalEvent.dataTransfer.files);
return false;
},
onImageDragOver: function (e) {
e.preventDefault();
e.originalEvent.dataTransfer.dropEffect = 'Copy';
return false;
}
};
$(document).on('pageshow', "#userImagePage", UserImagePage.onPageShow).on('pagehide', "#userImagePage", UserImagePage.onPageHide);

View File

@ -0,0 +1,76 @@
var UserProfilesPage = {
onPageShow: function () {
UserProfilesPage.loadPageData();
},
loadPageData: function () {
Dashboard.showLoadingMsg();
ApiClient.getAllUsers().done(UserProfilesPage.renderUsers);
},
renderUsers: function (users) {
var html = "";
html += '<li data-role="list-divider"><h3>Users</h3></li>';
for (var i = 0, length = users.length; i < length; i++) {
var user = users[i];
html += "<li>";
html += "<a onclick='Dashboard.navigate(\"editUser.html?userId=" + user.Id + "\");' href='#'>";
if (user.PrimaryImageTag) {
var url = ApiClient.getUserImageUrl(user.Id, {
width: 225,
tag: user.PrimaryImageTag,
type: "Primary"
});
html += "<img src='" + url + "' />";
} else {
html += "<img src='css/images/userFlyoutDefault.png' />";
}
html += "<h3>" + user.Name + "</h3>";
html += "</a>";
html += "<a onclick='UserProfilesPage.deleteUser(this);' data-userid='" + user.Id + "' data-username='" + user.Name + "' href='#'>Delete</a>";
html += "</li>";
}
$('#ulUserProfiles', $('#userProfilesPage')).html(html).listview('refresh');
Dashboard.hideLoadingMsg();
},
deleteUser: function (link) {
var name = link.getAttribute('data-username');
var msg = "Are you sure you wish to delete " + name + "?";
Dashboard.confirm(msg, "Delete User", function (result) {
if (result) {
Dashboard.showLoadingMsg();
var id = link.getAttribute('data-userid');
ApiClient.deleteUser(id).done(function () {
Dashboard.validateCurrentUser();
UserProfilesPage.loadPageData();
});
}
});
}
};
$(document).on('pageshow', "#userProfilesPage", UserProfilesPage.onPageShow);

View File

@ -0,0 +1,17 @@
var WizardStartPage = {
gotoNextPage: function () {
ApiClient.getAllUsers().done(function (users) {
if (users.length > 1) {
Dashboard.navigate('wizardLibrary.html');
} else {
Dashboard.navigate('wizardUser.html');
}
});
}
};

View File

@ -0,0 +1,59 @@
var WizardUserPage = {
onPageShow: function () {
Dashboard.showLoadingMsg();
var page = this;
ApiClient.getAllUsers().done(function (users) {
var user = users[0] || { Name: "User" };
$('#txtUsername', page).val(user.Name);
Dashboard.hideLoadingMsg();
});
},
onSubmit: function() {
Dashboard.showLoadingMsg();
var page = $.mobile.activePage;
ApiClient.getAllUsers().done(function (users) {
var user;
if (users.length) {
user = users[0];
user.Name = $('#txtUsername', page).val();
ApiClient.updateUser(user).done(WizardUserPage.saveComplete);
} else {
user = { Name: $('#txtUsername', page).val() };
ApiClient.createUser(user).done(WizardUserPage.saveComplete);
}
});
return false;
},
saveComplete: function () {
Dashboard.hideLoadingMsg();
Dashboard.navigate('wizardLibrary.html');
}
};
$(document).on('pageshow', "#wizardUserPage", WizardUserPage.onPageShow);

1185
Html/scripts/site.js Normal file

File diff suppressed because it is too large Load Diff

42
Html/support.html Normal file
View File

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<title>Support</title>
</head>
<body>
<div id="supportPage" data-role="page" class="page type-interior">
<div data-role="content">
<div class="content-primary">
<div class="readOnlyContent">
<div data-role="controlgroup" data-type="horizontal" class="localnav" data-mini="true">
<a href="support.html" data-role="button" class="ui-btn-active">General</a>
<a href="log.html" data-role="button">View Log</a>
<a href="supporter.html" data-role="button">Become a Supporter</a>
<a href="supporterKey.html" data-role="button">Supporter Key</a>
</div>
<h2>General Help</h2>
<p>
Media Browser has a thriving community of users and a vast knowledge base of information to help you get the most
out of your media collection.
</p>
<p>
The Community Tracker is a place where you can ask questions, post feature requests and report bugs and get timely
<em>and friendly</em> help from a thriving community of users and developers.
</p>
<a data-role="button" data-icon="arrow-r" data-iconpos="right" href="http://community.mediabrowser.tv" target="_blank">Visit the Community Tracker</a>
<p>
Also, within the tracker, there is a large Knowledge Base of information compiled from users and developers to help you get the
most out of Media Browser.
</p>
<a data-role="button" data-icon="search" data-iconpos="right" href="http://community.mediabrowser.tv/topics?category_id=5&&status=published" target="_blank">Search the Knowledge Base</a>
<p>
Finally, you can visit the Media Browser Web site to see what's happening with MB now and keep up with the developer blog.
</p>
<a data-role="button" data-icon="home" data-iconpos="right" href="http://forum.mediabrowser3.com" target="_blank">Visit the Media Browser Web Site</a>
</div>
</div>
</div>
</div>
</body>
</html>

69
Html/supporter.html Normal file
View File

@ -0,0 +1,69 @@
<!DOCTYPE html>
<html>
<head>
<title>Support</title>
</head>
<body>
<div id="supporterPage" data-role="page" class="page type-interior">
<div data-role="content">
<div class="content-primary">
<div class="readOnlyContent">
<div data-role="controlgroup" data-type="horizontal" class="localnav" data-mini="true">
<a href="support.html" data-role="button">General</a>
<a href="log.html" data-role="button">View Log</a>
<a href="supporter.html" data-role="button" class="ui-btn-active">Become a Supporter</a>
<a href="supporterKey.html" data-role="button">Supporter Key</a>
</div>
<h2>Support the Media Browser Team</h2>
<p>
By becoming a Media Browser Supporter, you ensure the continued development and support of this product <strong>and open up a whole new world of premium plug-ins.</strong>
</p>
<p style="margin-bottom: 30px">
A portion of all MB3 Supporter donations is also contributed to some of our metadata providers (<a href="http://themoviedb.org" target="_blank">The Movie Db</a>,
<a href="http://thetvdb.com" target="_blank">The TVdb</a>, and <a href="http://fanart.tv" target="_blank">FanArt.tv</a>)
</p>
<p style="margin-bottom: 30px">
Premium plug-ins can be installed and used for their trial periods (14 days on any particular machine) but, to register them for use
beyond that period, you also have to be a Media Browser Supporter.
</p>
<div style="display: none; padding: 10px 10px 10px 10px; margin-bottom: 10px" class="ui-bar-e supporterOnly">
<p>
<strong><em>Thank You</em></strong> for your past support of the Media Browser Team. Users like you make it possible for
Media Browser to exist and keep getting better and better. You can always support us again if you feel you are getting maximum
value from the product.
</p>
</div>
<form name="_xclick" action="https://www.paypal.com/cgi-bin/webscr"
method="post">
<label for="donateAmt" >Amount (USD)</label>
<select id="donateAmt" name="amount" >
<option>10</option>
<option>15</option>
<option>20</option>
<option>30</option>
<option>50</option>
</select>
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="donate@mediabrowser3.com">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="item_name" value="Media Browser Supporter">
<input type="hidden" name="item_number" value="MBSupporter">
<input type="hidden" name="notify_url" value="http://mb3admin.com/admin/service/services/ppipn.php">
<input type="hidden" name="return" id ="paypalReturnUrl" value="#">
<a data-role="button" onclick="_xclick.submit();"><img src="css/images/donatepp.png"/></a>
<p><small><em>This button is now <strong>live</strong>. Transactions will result in real money being transferred.</em></small></p>
</form>
</div>
</div>
</div>
</div>
</body>
</html>

73
Html/supporterKey.html Normal file
View File

@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<title>Support</title>
</head>
<body>
<div id="supporterKeyPage" data-role="page" class="page type-interior">
<div data-role="content">
<div class="content-primary">
<div class="readOnlyContent">
<div data-role="controlgroup" data-type="horizontal" class="localnav" data-mini="true">
<a href="support.html" data-role="button">General</a>
<a href="log.html" data-role="button">View Log</a>
<a href="supporter.html" data-role="button">Become a Supporter</a>
<a href="supporterKey.html" data-role="button" class="ui-btn-active">Supporter Key</a>
</div>
<h2>Supporter Key</h2>
</div>
<form id="supporterKeyForm">
<div style="margin-top: 40px; margin-bottom: 40px">
<label for="txtSupporterKey">MB3 Supporter Key (paste from email)</label>
<input type="password" id="txtSupporterKey" name="txtSupporterKey" data-inline="true" />
<div class="fieldDescription">
<strong>After becoming a supporter, you will be emailed a Supporter Key. Simply copy and paste that key into this field and start
enjoying everything the community has developed for Media Browser. <em>Only MB 3 Supporter Keys are valid here</em></strong>
</div>
</div>
<div style="margin-top: 40px; margin-bottom: 40px">
<label for="txtLegacyKey">Legacy Supporter Key (from MB 2.x)</label>
<input type="password" id="txtLegacyKey" name="txtLegacyKey" data-inline="true" />
<div class="fieldDescription">
<strong>Some premium plug-ins may give credit for registrations with previous versions in MB 2.x. Enter your MB 2.x
Supporter Key here to allow that credit.
</strong>
</div>
</div>
<p>
<button type="submit" id="mbLegacyKeyBtn" data-theme="b">Save</button>
</p>
</form>
<hr/>
<h2>Lost Key</h2>
<form id="lostKeyForm">
<div style="margin-top: 40px; margin-bottom: 40px">
<label for="txtEmail">Email Address</label>
<input type="email" required id="txtEmail" name="txtEmail" data-inline="true" />
<div class="fieldDescription">
<strong>If you have lost your key, enter the email address associated with your PayPal account here and hit "Retrieve Key". The key
will be emailed to you and you can come back here and paste it above.</strong>
</div>
</div>
<p>
<button type="submit" id="mbRetrieveKeyBtn" data-theme="b" >Retrieve Key</button>
</p>
</form>
</div>
</div>
<script type="text/javascript">
$('#supporterKeyForm').on('submit', SupporterKeyPage.updateSupporterKey);
$('#lostKeyForm').on('submit', SupporterKeyPage.retrieveSupporterKey);
</script>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Some files were not shown because too many files have changed in this diff Show More