From 6f2b1c2ef8eb64cba998fea4c9b7e821bdf6895f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 21 May 2016 22:28:47 -0400 Subject: [PATCH] use shared collectioneditor --- .../collectioneditor/collectioneditor.js | 264 ++++++++++++++++++ .../emby-select/emby-select.css | 44 +++ .../emby-select/emby-select.js | 112 ++++++++ .../collectioneditor/collectioneditor.js | 239 ---------------- dashboard-ui/scripts/librarybrowser.js | 7 +- dashboard-ui/scripts/librarylist.js | 13 +- dashboard-ui/scripts/moviecollections.js | 8 +- dashboard-ui/scripts/site.js | 3 +- .../thirdparty/paper-button-style.css | 6 +- 9 files changed, 447 insertions(+), 249 deletions(-) create mode 100644 dashboard-ui/bower_components/emby-webcomponents/collectioneditor/collectioneditor.js create mode 100644 dashboard-ui/bower_components/emby-webcomponents/emby-select/emby-select.css create mode 100644 dashboard-ui/bower_components/emby-webcomponents/emby-select/emby-select.js delete mode 100644 dashboard-ui/components/collectioneditor/collectioneditor.js diff --git a/dashboard-ui/bower_components/emby-webcomponents/collectioneditor/collectioneditor.js b/dashboard-ui/bower_components/emby-webcomponents/collectioneditor/collectioneditor.js new file mode 100644 index 000000000..d16a5b0fa --- /dev/null +++ b/dashboard-ui/bower_components/emby-webcomponents/collectioneditor/collectioneditor.js @@ -0,0 +1,264 @@ +define(['dialogHelper', 'loading', 'connectionManager', 'embyRouter', 'globalize', 'paper-checkbox', 'paper-input', 'paper-icon-button-light', 'emby-select'], function (dialogHelper, loading, connectionManager, embyRouter, globalize) { + + var currentServerId; + + function parentWithClass(elem, className) { + + while (!elem.classList || !elem.classList.contains(className)) { + elem = elem.parentNode; + + if (!elem) { + return null; + } + } + + return elem; + } + + function onSubmit(e) { + loading.show(); + + var panel = parentWithClass(this, 'dialog'); + + var collectionId = panel.querySelector('#selectCollectionToAddTo').value; + + var apiClient = connectionManager.getApiClient(currentServerId); + + if (collectionId) { + addToCollection(apiClient, panel, collectionId); + } else { + createCollection(apiClient, panel); + } + + e.preventDefault(); + return false; + } + + function createCollection(apiClient, dlg) { + + var url = apiClient.getUrl("Collections", { + + Name: dlg.querySelector('#txtNewCollectionName').value, + IsLocked: !dlg.querySelector('#chkEnableInternetMetadata').checked, + Ids: dlg.querySelector('.fldSelectedItemIds').value || '' + + //ParentId: getParameterByName('parentId') || LibraryMenu.getTopParentId() + + }); + + apiClient.ajax({ + type: "POST", + url: url, + dataType: "json" + + }).then(function (result) { + + loading.hide(); + + var id = result.Id; + + dialogHelper.close(dlg); + redirectToCollection(apiClient, id); + + }); + } + + function redirectToCollection(apiClient, id) { + + apiClient.getItem(apiClient.getCurrentUserId(), id).then(function (item) { + + embyRouter.showItem(item); + }); + } + + function addToCollection(apiClient, dlg, id) { + + var url = apiClient.getUrl("Collections/" + id + "/Items", { + + Ids: dlg.querySelector('.fldSelectedItemIds').value || '' + }); + + apiClient.ajax({ + type: "POST", + url: url + + }).then(function () { + + loading.hide(); + + dialogHelper.close(dlg); + + require(['toast'], function (toast) { + toast(globalize.translate('MessageItemsAdded')); + }); + }); + } + + function onDialogClosed() { + + loading.hide(); + } + + function triggerChange(select) { + select.dispatchEvent(new CustomEvent('change', {})); + } + + function populateCollections(panel) { + + loading.show(); + + var select = panel.querySelector('#selectCollectionToAddTo'); + + panel.querySelector('.newCollectionInfo').classList.add('hide'); + + var options = { + + Recursive: true, + IncludeItemTypes: "BoxSet", + SortBy: "SortName" + }; + + var apiClient = connectionManager.getApiClient(currentServerId); + apiClient.getItems(apiClient.getCurrentUserId(), options).then(function (result) { + + var html = ''; + + html += ''; + + html += result.Items.map(function (i) { + + return ''; + }); + + select.innerHTML = html; + select.value = ''; + triggerChange(select); + + loading.hide(); + }); + } + + function getEditorHtml() { + + var html = ''; + + html += '
'; + + html += '
'; + html += globalize.translate('CreateCollectionHelp'); + html += '
'; + + html += '
'; + html += '
'; + html += '
'; + html += ''; + html += '
'; + + html += '
'; + + html += '
'; + html += ''; + html += '
' + globalize.translate('NewCollectionNameExample') + '
'; + html += '
'; + + html += '
'; + html += '
'; + + html += '
'; + html += '' + globalize.translate('OptionSearchForInternetMetadata') + ''; + html += '
'; + + // newCollectionInfo + html += '
'; + + html += '
'; + html += '
'; + html += ''; + html += '
'; + + html += ''; + + html += '
'; + + return html; + } + + function initEditor(content, items) { + + content.querySelector('#selectCollectionToAddTo').addEventListener('change', function () { + if (this.value) { + content.querySelector('.newCollectionInfo').classList.add('hide'); + content.querySelector('#txtNewCollectionName').removeAttribute('required'); + } else { + content.querySelector('.newCollectionInfo').classList.remove('hide'); + content.querySelector('#txtNewCollectionName').setAttribute('required', 'required'); + } + }); + + content.querySelector('.newCollectionForm').addEventListener('submit', onSubmit); + + content.querySelector('.fldSelectedItemIds', content).value = items.join(','); + + if (items.length) { + content.querySelector('.fldSelectCollection').classList.remove('hide'); + populateCollections(content); + } else { + content.querySelector('.fldSelectCollection').classList.add('hide'); + + var selectCollectionToAddTo = content.querySelector('#selectCollectionToAddTo'); + selectCollectionToAddTo.innerHTML = ''; + selectCollectionToAddTo.value = ''; + triggerChange(selectCollectionToAddTo); + } + } + + function collectioneditor() { + + var self = this; + + self.show = function (options) { + + var items = options.items || {}; + currentServerId = options.serverId; + + var dlg = dialogHelper.createDialog({ + size: 'small', + removeOnClose: true + }); + + dlg.classList.add('ui-body-b'); + dlg.classList.add('background-theme-b'); + + var html = ''; + var title = items.length ? globalize.translate('HeaderAddToCollection') : globalize.translate('HeaderNewCollection'); + + html += '
'; + html += ''; + html += '
'; + html += title; + html += '
'; + + html += '' + globalize.translate('ButtonHelp') + ''; + + html += '
'; + + html += getEditorHtml(); + + dlg.innerHTML = html; + document.body.appendChild(dlg); + + initEditor(dlg, items); + + dlg.addEventListener('close', onDialogClosed); + + dialogHelper.open(dlg); + + dlg.querySelector('.btnCancel').addEventListener('click', function () { + + dialogHelper.close(dlg); + }); + }; + } + + return collectioneditor; +}); \ No newline at end of file diff --git a/dashboard-ui/bower_components/emby-webcomponents/emby-select/emby-select.css b/dashboard-ui/bower_components/emby-webcomponents/emby-select/emby-select.css new file mode 100644 index 000000000..2b1993d4f --- /dev/null +++ b/dashboard-ui/bower_components/emby-webcomponents/emby-select/emby-select.css @@ -0,0 +1,44 @@ +[is="emby-select"] { + display: block; + margin: 0; + margin-bottom: 0 !important; + background: none; + border: 1px solid rgb(221, 221, 221); + border-width: 0 0 1px 0; + /* Prefixed box-sizing rules necessary for older browsers */ + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + /* Remove select styling */ + /* Font size must the 16px or larger to prevent iOS page zoom on focus */ + font-size: inherit; + /* General select styles: change as needed */ + font-family: inherit; + font-weight: bold; + color: inherit; + padding: .6em .8em .3em 0; + cursor: pointer; + outline: none !important; +} + +.selectLabel { + display: block; +} + +.selectLabelFocus { + color: #52B54B; +} + +.emby-select-selectionbar { + height: 2px; + transform: scale(.01); + transition: transform .2s ease-out; + position: relative; + top: -1px; + margin-bottom: .5em; +} + +[is="emby-select"]:focus + .emby-select-selectionbar { + background-color: #52B54B; + transform: none; +} diff --git a/dashboard-ui/bower_components/emby-webcomponents/emby-select/emby-select.js b/dashboard-ui/bower_components/emby-webcomponents/emby-select/emby-select.js new file mode 100644 index 000000000..4f41cb6e1 --- /dev/null +++ b/dashboard-ui/bower_components/emby-webcomponents/emby-select/emby-select.js @@ -0,0 +1,112 @@ +define(['layoutManager', 'browser', 'actionsheet', 'css!./emby-select'], function (layoutManager, browser, actionsheet) { + + var EmbySelectPrototype = Object.create(HTMLSelectElement.prototype); + + function enableNativeMenu() { + + // Take advantage of the native input methods + if (browser.tv) { + return true; + } + + if (layoutManager.tv) { + return false; + } + + return true; + } + + function showActionSheeet(select) { + + actionsheet.show({ + items: select.options, + positionTo: select + + }).then(function (value) { + select.value = value; + }); + } + + function getLabel(select) { + var elem = select.previousSibling; + while (elem && elem.tagName != 'LABEL') { + elem = elem.previousSibling; + } + return elem; + } + + function onFocus(e) { + var label = getLabel(this); + if (label) { + label.classList.add('selectLabelFocus'); + } + } + + function onBlur(e) { + var label = getLabel(this); + if (label) { + label.classList.remove('selectLabelFocus'); + } + } + + function onMouseDown(e) { + + if (!enableNativeMenu()) { + e.preventDefault(); + showActionSheeet(this); + } + } + + function onKeyDown(e) { + + switch (e.keyCode) { + + case 13: + if (!enableNativeMenu()) { + e.preventDefault(); + showActionSheeet(this); + } + return; + case 37: + case 38: + case 39: + case 40: + if (layoutManager.tv) { + e.preventDefault(); + } + return; + default: + break; + } + } + + EmbySelectPrototype.createdCallback = function () { + + if (!this.id) { + this.id = 'select' + new Date().getTime(); + } + this.addEventListener('mousedown', onMouseDown); + this.addEventListener('keydown', onKeyDown); + this.addEventListener('focus', onFocus); + this.addEventListener('keydown', onBlur); + }; + + EmbySelectPrototype.attachedCallback = function () { + + var label = this.ownerDocument.createElement('label'); + label.innerHTML = this.getAttribute('label') || ''; + label.classList.add('selectLabel'); + label.htmlFor = this.id; + this.parentNode.insertBefore(label, this); + + var div = document.createElement('div'); + div.classList.add('emby-select-selectionbar'); + div.innerHTML = '
'; + this.parentNode.insertBefore(div, this.nextSibling); + }; + + document.registerElement('emby-select', { + prototype: EmbySelectPrototype, + extends: 'select' + }); +}); \ No newline at end of file diff --git a/dashboard-ui/components/collectioneditor/collectioneditor.js b/dashboard-ui/components/collectioneditor/collectioneditor.js deleted file mode 100644 index d82b2d984..000000000 --- a/dashboard-ui/components/collectioneditor/collectioneditor.js +++ /dev/null @@ -1,239 +0,0 @@ -define(['dialogHelper', 'jQuery', 'paper-checkbox', 'paper-input', 'paper-icon-button-light'], function (dialogHelper, $) { - - function onSubmit() { - Dashboard.showLoadingMsg(); - - var panel = $(this).parents('.dialog')[0]; - - var collectionId = $('#selectCollectionToAddTo', panel).val(); - - if (collectionId) { - addToCollection(panel, collectionId); - } else { - createCollection(panel); - } - - return false; - } - - function createCollection(dlg) { - - var url = ApiClient.getUrl("Collections", { - - Name: $('#txtNewCollectionName', dlg).val(), - IsLocked: !$('#chkEnableInternetMetadata', dlg).checked(), - Ids: $('.fldSelectedItemIds', dlg).val() || '' - - //ParentId: getParameterByName('parentId') || LibraryMenu.getTopParentId() - - }); - - ApiClient.ajax({ - type: "POST", - url: url, - dataType: "json" - - }).then(function (result) { - - Dashboard.hideLoadingMsg(); - - var id = result.Id; - - dialogHelper.close(dlg); - redirectToCollection(id); - - }); - } - - function redirectToCollection(id) { - - var context = getParameterByName('context'); - - ApiClient.getItem(Dashboard.getCurrentUserId(), id).then(function (item) { - - Dashboard.navigate(LibraryBrowser.getHref(item, context)); - - }); - } - - function addToCollection(dlg, id) { - - var url = ApiClient.getUrl("Collections/" + id + "/Items", { - - Ids: $('.fldSelectedItemIds', dlg).val() || '' - }); - - ApiClient.ajax({ - type: "POST", - url: url - - }).then(function () { - - Dashboard.hideLoadingMsg(); - - dialogHelper.close(dlg); - - require(['toast'], function (toast) { - toast(Globalize.translate('MessageItemsAdded')); - }); - }); - } - - function onDialogClosed() { - - $(this).remove(); - Dashboard.hideLoadingMsg(); - } - - function populateCollections(panel) { - - Dashboard.showLoadingMsg(); - - var select = $('#selectCollectionToAddTo', panel); - - $('.newCollectionInfo', panel).hide(); - - var options = { - - Recursive: true, - IncludeItemTypes: "BoxSet", - SortBy: "SortName" - }; - - ApiClient.getItems(Dashboard.getCurrentUserId(), options).then(function (result) { - - var html = ''; - - html += ''; - - html += result.Items.map(function (i) { - - return ''; - }); - - select.html(html).val('').trigger('change'); - - Dashboard.hideLoadingMsg(); - }); - } - - function getEditorHtml() { - - var html = ''; - - html += '
'; - - html += '
'; - html += Globalize.translate('CreateCollectionHelp'); - html += '
'; - - html += '
'; - html += '
'; - html += '
'; - html += ''; - html += ''; - html += '
'; - - html += '
'; - - html += '
'; - html += ''; - html += '
' + Globalize.translate('NewCollectionNameExample') + '
'; - html += '
'; - - html += '
'; - html += '
'; - - html += '
'; - html += '' + Globalize.translate('OptionSearchForInternetMetadata') + ''; - html += '
'; - - // newCollectionInfo - html += '
'; - - html += '
'; - html += '
'; - html += ''; - html += '
'; - - html += ''; - - html += '
'; - - return html; - } - - function initEditor(content, items) { - - $('#selectCollectionToAddTo', content).on('change', function () { - - if (this.value) { - $('.newCollectionInfo', content).hide(); - $('#txtNewCollectionName', content).removeAttr('required'); - } else { - $('.newCollectionInfo', content).show(); - $('#txtNewCollectionName', content).attr('required', 'required'); - } - }); - - $('.newCollectionForm', content).off('submit', onSubmit).on('submit', onSubmit); - - $('.fldSelectedItemIds', content).val(items.join(',')); - - if (items.length) { - $('.fldSelectCollection', content).show(); - populateCollections(content); - } else { - $('.fldSelectCollection', content).hide(); - $('#selectCollectionToAddTo', content).html('').val('').trigger('change'); - } - } - - function collectioneditor() { - - var self = this; - - self.show = function (items) { - - items = items || []; - - var dlg = dialogHelper.createDialog({ - size: 'small' - }); - - dlg.classList.add('ui-body-b'); - dlg.classList.add('background-theme-b'); - - var html = ''; - var title = items.length ? Globalize.translate('HeaderAddToCollection') : Globalize.translate('HeaderNewCollection'); - - html += '
'; - html += ''; - html += '
'; - html += title; - html += '
'; - - html += '' + Globalize.translate('ButtonHelp') + ''; - - html += '
'; - - html += getEditorHtml(); - - dlg.innerHTML = html; - document.body.appendChild(dlg); - - initEditor(dlg, items); - - $(dlg).on('close', onDialogClosed); - - dialogHelper.open(dlg); - - $('.btnCancel', dlg).on('click', function () { - - dialogHelper.close(dlg); - }); - }; - } - - return collectioneditor; -}); \ No newline at end of file diff --git a/dashboard-ui/scripts/librarybrowser.js b/dashboard-ui/scripts/librarybrowser.js index 2a5616e31..21fffed15 100644 --- a/dashboard-ui/scripts/librarybrowser.js +++ b/dashboard-ui/scripts/librarybrowser.js @@ -929,9 +929,12 @@ }); break; case 'addtocollection': - require(['collectioneditor'], function (collectioneditor) { + require(['collectionEditor'], function (collectionEditor) { - new collectioneditor().show([itemId]); + new collectionEditor().show({ + items: [itemId], + serverId: serverId + }); }); break; case 'playlist': diff --git a/dashboard-ui/scripts/librarylist.js b/dashboard-ui/scripts/librarylist.js index 76b192d41..88d6865d5 100644 --- a/dashboard-ui/scripts/librarylist.js +++ b/dashboard-ui/scripts/librarylist.js @@ -494,9 +494,12 @@ switch (id) { case 'addtocollection': - require(['collectioneditor'], function (collectioneditor) { + require(['collectionEditor'], function (collectionEditor) { - new collectioneditor().show([itemId]); + new collectionEditor().show({ + items: [itemId], + serverId: serverId + }); }); break; case 'playlist': @@ -1232,9 +1235,11 @@ switch (id) { case 'addtocollection': - require(['collectioneditor'], function (collectioneditor) { + require(['collectionEditor'], function (collectionEditor) { - new collectioneditor().show(items); + new collectionEditor().show({ + items: items + }); }); hideSelections(); break; diff --git a/dashboard-ui/scripts/moviecollections.js b/dashboard-ui/scripts/moviecollections.js index 28c154314..6d5a284da 100644 --- a/dashboard-ui/scripts/moviecollections.js +++ b/dashboard-ui/scripts/moviecollections.js @@ -189,9 +189,13 @@ // The button is created dynamically $('.btnNewCollection', tabContent).on('click', function () { - require(['collectioneditor'], function (collectioneditor) { + require(['collectionEditor'], function (collectionEditor) { - new collectioneditor().show(); + var serverId = ApiClient.serverInfo().Id; + new collectionEditor().show({ + items: [], + serverId: serverId + }); }); }); diff --git a/dashboard-ui/scripts/site.js b/dashboard-ui/scripts/site.js index e00bdadf1..9c6463b67 100644 --- a/dashboard-ui/scripts/site.js +++ b/dashboard-ui/scripts/site.js @@ -1709,7 +1709,6 @@ var AppInfo = {}; ironCardList: 'components/ironcardlist/ironcardlist', scrollThreshold: 'components/scrollthreshold', directorybrowser: 'components/directorybrowser/directorybrowser', - collectioneditor: 'components/collectioneditor/collectioneditor', playlisteditor: 'components/playlisteditor/playlisteditor', medialibrarycreator: 'components/medialibrarycreator/medialibrarycreator', medialibraryeditor: 'components/medialibraryeditor/medialibraryeditor', @@ -1768,11 +1767,13 @@ var AppInfo = {}; define("libjass", [bowerPath + "/libjass/libjass", "css!" + bowerPath + "/libjass/libjass"], returnFirstDependency); + define("collectionEditor", [embyWebComponentsBowerPath + "/collectioneditor/collectioneditor"], returnFirstDependency); define("recordingCreator", [embyWebComponentsBowerPath + "/recordingcreator/recordingcreator"], returnFirstDependency); define("recordingEditor", [embyWebComponentsBowerPath + "/recordingcreator/recordingeditor"], returnFirstDependency); define("mediaInfo", [embyWebComponentsBowerPath + "/mediainfo/mediainfo"], returnFirstDependency); define("backdrop", [embyWebComponentsBowerPath + "/backdrop/backdrop"], returnFirstDependency); define("fetchHelper", [embyWebComponentsBowerPath + "/fetchhelper"], returnFirstDependency); + define("emby-select", [embyWebComponentsBowerPath + "/emby-select/emby-select"], returnFirstDependency); define("tvguide", [embyWebComponentsBowerPath + "/guide/guide", 'embyRouter'], returnFirstDependency); diff --git a/dashboard-ui/thirdparty/paper-button-style.css b/dashboard-ui/thirdparty/paper-button-style.css index 5c4609ba0..25d9978eb 100644 --- a/dashboard-ui/thirdparty/paper-button-style.css +++ b/dashboard-ui/thirdparty/paper-button-style.css @@ -432,7 +432,11 @@ paper-input label, paper-textarea label { margin-bottom: .5em; } -.ui-body-b .paper-input-container-0 .input-content.paper-input-container label, .ui-body-b .paper-input-container-0 .input-content.paper-input-container .paper-input-label, .ui-body-b paper-textarea label, .ui-body-b .selectLabel, .ui-body-b .paperListLabel, .ui-body-b .fieldDescription { +.ui-body-b .paper-input-container-0 .input-content.paper-input-container label, .ui-body-b .paper-input-container-0 .input-content.paper-input-container .paper-input-label, .ui-body-b paper-textarea label, .ui-body-b .paperListLabel, .ui-body-b .fieldDescription { + color: #ccc; +} + +.ui-body-b .selectLabel:not(.selectLabelFocus) { color: #ccc; }