diff --git a/src/components/autoFocuser.js b/src/components/autoFocuser.js new file mode 100644 index 000000000..65358b1bc --- /dev/null +++ b/src/components/autoFocuser.js @@ -0,0 +1,64 @@ +define(["focusManager"], function (focusManager) { + "use strict"; + + /** + * Previously selected element. + */ + var activeElement; + + /** + * Start AutoFocuser + */ + function enable() { + window.addEventListener("focusin", function (e) { + activeElement = e.target; + }); + + console.log("AutoFocuser enabled"); + } + + /** + * Set focus on a suitable element, taking into account the previously selected. + */ + function autoFocus(container) { + container = container || document.body; + + var candidates = []; + + if (activeElement) { + // These elements are recreated + if (activeElement.classList.contains("btnPreviousPage")) { + candidates.push(container.querySelector(".btnPreviousPage")); + candidates.push(container.querySelector(".btnNextPage")); + } else if (activeElement.classList.contains("btnNextPage")) { + candidates.push(container.querySelector(".btnNextPage")); + candidates.push(container.querySelector(".btnPreviousPage")); + } else if (activeElement.classList.contains("btnSelectView")) { + candidates.push(container.querySelector(".btnSelectView")); + } + + candidates.push(activeElement); + } + + candidates = candidates.concat(Array.from(container.querySelectorAll(".btnResume"))); + candidates = candidates.concat(Array.from(container.querySelectorAll(".btnPlay"))); + + var notFound = candidates.every(function (element) { + if (focusManager.isCurrentlyFocusable(element)) { + focusManager.focus(element); + return false; + } + + return true; + }); + + if (notFound) { + focusManager.autoFocus(container); + } + } + + return { + enable: enable, + autoFocus: autoFocus + }; +}); diff --git a/src/controllers/addserver.js b/src/controllers/addserver.js index 55b670f54..a55ba3066 100644 --- a/src/controllers/addserver.js +++ b/src/controllers/addserver.js @@ -46,6 +46,10 @@ define(["appSettings", "loading", "browser", "emby-button"], function(appSetting view.querySelector(".addServerForm").addEventListener("submit", onServerSubmit); view.querySelector(".btnCancel").addEventListener("click", goBack); + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(view); + }); + function onServerSubmit(e) { submitServer(view); e.preventDefault(); diff --git a/src/controllers/itemdetailpage.js b/src/controllers/itemdetailpage.js index 5bc54edf7..b14591274 100644 --- a/src/controllers/itemdetailpage.js +++ b/src/controllers/itemdetailpage.js @@ -617,24 +617,9 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild hideAll(page, "btnDownload", true); } - try { - require(["focusManager"], function (focusManager) { - [".btnResume", ".btnPlay"].every(function (cls) { - var elems = page.querySelectorAll(cls); - - for (var i = 0; i < elems.length; i++) { - if (focusManager.isCurrentlyFocusable(elems[i])) { - focusManager.focus(elems[i]); - return false; - } - } - - return true; - }); - }); - } catch (e) { - console.log(e); - } + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(page); + }); } function logoImageUrl(item, apiClient, options) { diff --git a/src/controllers/loginpage.js b/src/controllers/loginpage.js index ef54d20bf..8dd041a9f 100644 --- a/src/controllers/loginpage.js +++ b/src/controllers/loginpage.js @@ -116,6 +116,10 @@ define(["apphost", "appSettings", "dom", "connectionManager", "loading", "layout view.querySelector(".visualLoginForm").classList.remove("hide"); view.querySelector(".manualLoginForm").classList.add("hide"); view.querySelector(".btnManual").classList.remove("hide"); + + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(view); + }); } view.querySelector("#divUsers").addEventListener("click", function(e) { diff --git a/src/controllers/movies/moviecollections.js b/src/controllers/movies/moviecollections.js index d5bd96d34..f17f64b7c 100644 --- a/src/controllers/movies/moviecollections.js +++ b/src/controllers/movies/moviecollections.js @@ -172,6 +172,10 @@ define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardB libraryBrowser.saveQueryValues(getSavedQueryKey(page), query); loading.hide(); isLoading = false; + + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(page); + }); }); } diff --git a/src/controllers/movies/movies.js b/src/controllers/movies/movies.js index b4e30602f..3a365acc9 100644 --- a/src/controllers/movies/movies.js +++ b/src/controllers/movies/movies.js @@ -77,6 +77,10 @@ define(["loading", "layoutManager", "userSettings", "events", "libraryBrowser", isLoading = false; loading.hide(); + + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(tabContent); + }); } function getItemsHtml(items) { diff --git a/src/controllers/music/musicalbums.js b/src/controllers/music/musicalbums.js index ac45d9a15..0cfb61e2b 100644 --- a/src/controllers/music/musicalbums.js +++ b/src/controllers/music/musicalbums.js @@ -160,6 +160,10 @@ define(["layoutManager", "playbackManager", "loading", "events", "libraryBrowser libraryBrowser.saveQueryValues(getSavedQueryKey(), query); loading.hide(); isLoading = false; + + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(tabContent); + }); }); } diff --git a/src/controllers/music/musicartists.js b/src/controllers/music/musicartists.js index 5159f635f..aaeea8c88 100644 --- a/src/controllers/music/musicartists.js +++ b/src/controllers/music/musicartists.js @@ -144,6 +144,10 @@ define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", " libraryBrowser.saveQueryValues(getSavedQueryKey(page), query); loading.hide(); isLoading = false; + + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(tabContent); + }); }); } diff --git a/src/controllers/music/musicgenres.js b/src/controllers/music/musicgenres.js index ed1efc0a6..e357cdabb 100644 --- a/src/controllers/music/musicgenres.js +++ b/src/controllers/music/musicgenres.js @@ -87,6 +87,10 @@ define(["libraryBrowser", "cardBuilder", "apphost", "imageLoader", "loading"], f imageLoader.lazyChildren(elem); libraryBrowser.saveQueryValues(getSavedQueryKey(), query); loading.hide(); + + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(context); + }); }); } diff --git a/src/controllers/music/musicplaylists.js b/src/controllers/music/musicplaylists.js index 964896077..fd458c88a 100644 --- a/src/controllers/music/musicplaylists.js +++ b/src/controllers/music/musicplaylists.js @@ -58,6 +58,10 @@ define(["libraryBrowser", "cardBuilder", "apphost", "imageLoader", "loading"], f imageLoader.lazyChildren(elem); libraryBrowser.saveQueryValues(getSavedQueryKey(), query); loading.hide(); + + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(context); + }); }); } diff --git a/src/controllers/music/musicrecommended.js b/src/controllers/music/musicrecommended.js index fc3371833..556877aa1 100644 --- a/src/controllers/music/musicrecommended.js +++ b/src/controllers/music/musicrecommended.js @@ -59,6 +59,10 @@ define(["browser", "layoutManager", "userSettings", "inputManager", "loading", " }); imageLoader.lazyChildren(elem); loading.hide(); + + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(page); + }); }); } diff --git a/src/controllers/music/songs.js b/src/controllers/music/songs.js index 4806195ed..47263be0d 100644 --- a/src/controllers/music/songs.js +++ b/src/controllers/music/songs.js @@ -104,6 +104,10 @@ define(["events", "libraryBrowser", "imageLoader", "listView", "loading", "emby- libraryBrowser.saveQueryValues(getSavedQueryKey(page), query); loading.hide(); isLoading = false; + + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(page); + }); }); } diff --git a/src/controllers/shows/episodes.js b/src/controllers/shows/episodes.js index 42d9d89f7..9c61ac80d 100644 --- a/src/controllers/shows/episodes.js +++ b/src/controllers/shows/episodes.js @@ -144,6 +144,10 @@ define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardB libraryBrowser.saveQueryValues(getSavedQueryKey(page), query); loading.hide(); isLoading = false; + + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(page); + }); }); } diff --git a/src/controllers/shows/tvlatest.js b/src/controllers/shows/tvlatest.js index 2a1ed56bf..5862fce45 100644 --- a/src/controllers/shows/tvlatest.js +++ b/src/controllers/shows/tvlatest.js @@ -40,6 +40,10 @@ define(["loading", "components/groupedcards", "cardBuilder", "apphost", "imageLo elem.innerHTML = html; imageLoader.lazyChildren(elem); loading.hide(); + + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(context); + }); }); } diff --git a/src/controllers/shows/tvrecommended.js b/src/controllers/shows/tvrecommended.js index 1386e76a3..d1adb0434 100644 --- a/src/controllers/shows/tvrecommended.js +++ b/src/controllers/shows/tvrecommended.js @@ -97,6 +97,10 @@ define(["events", "inputManager", "libraryMenu", "layoutManager", "loading", "do cardLayout: false }); loading.hide(); + + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(view); + }); }); } diff --git a/src/controllers/shows/tvshows.js b/src/controllers/shows/tvshows.js index adccd9823..1dec53054 100644 --- a/src/controllers/shows/tvshows.js +++ b/src/controllers/shows/tvshows.js @@ -172,6 +172,10 @@ define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", " libraryBrowser.saveQueryValues(getSavedQueryKey(page), query); loading.hide(); isLoading = false; + + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(page); + }); }); } diff --git a/src/controllers/shows/tvstudios.js b/src/controllers/shows/tvstudios.js index 3c000a8e7..4e715e1fd 100644 --- a/src/controllers/shows/tvstudios.js +++ b/src/controllers/shows/tvstudios.js @@ -46,6 +46,10 @@ define(["loading", "libraryBrowser", "cardBuilder", "apphost"], function (loadin context: "tvshows" }); loading.hide(); + + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(context); + }); }); } diff --git a/src/controllers/user/display.js b/src/controllers/user/display.js index f91e874a8..aea471685 100644 --- a/src/controllers/user/display.js +++ b/src/controllers/user/display.js @@ -24,7 +24,8 @@ define(["displaySettings", "userSettingsBuilder", "userSettings"], function (Dis element: view.querySelector(".settingsContainer"), userSettings: userSettings, enableSaveButton: false, - enableSaveConfirmation: false + enableSaveConfirmation: false, + autoFocus: true }); } }); diff --git a/src/controllers/user/home.js b/src/controllers/user/home.js index 5794d5872..7f1e1a485 100644 --- a/src/controllers/user/home.js +++ b/src/controllers/user/home.js @@ -24,7 +24,8 @@ define(["homescreenSettings", "userSettingsBuilder", "dom", "globalize", "loadin element: view.querySelector(".homeScreenSettingsContainer"), userSettings: userSettings, enableSaveButton: false, - enableSaveConfirmation: false + enableSaveConfirmation: false, + autoFocus: true }); } }); diff --git a/src/controllers/user/menu.js b/src/controllers/user/menu.js index d9fa2ab99..4e0a7824b 100644 --- a/src/controllers/user/menu.js +++ b/src/controllers/user/menu.js @@ -35,6 +35,10 @@ define(["apphost", "connectionManager", "listViewStyle", "emby-button"], functio page.querySelector(".adminSection").classList.add("hide"); } }); + + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(view); + }); }); }; }); diff --git a/src/controllers/user/playback.js b/src/controllers/user/playback.js index f2463ad8d..a3661e409 100644 --- a/src/controllers/user/playback.js +++ b/src/controllers/user/playback.js @@ -24,7 +24,8 @@ define(["playbackSettings", "userSettingsBuilder", "dom", "globalize", "loading" element: view.querySelector(".settingsContainer"), userSettings: userSettings, enableSaveButton: false, - enableSaveConfirmation: false + enableSaveConfirmation: false, + autoFocus: true }); } }); diff --git a/src/controllers/user/subtitles.js b/src/controllers/user/subtitles.js index 205265efc..2f4884859 100644 --- a/src/controllers/user/subtitles.js +++ b/src/controllers/user/subtitles.js @@ -24,7 +24,8 @@ define(["subtitleSettings", "userSettingsBuilder", "userSettings"], function (Su element: view.querySelector(".settingsContainer"), userSettings: userSettings, enableSaveButton: false, - enableSaveConfirmation: false + enableSaveConfirmation: false, + autoFocus: true }); } }); diff --git a/src/controllers/userpasswordpage.js b/src/controllers/userpasswordpage.js index 30ca06327..eeb9b25e3 100644 --- a/src/controllers/userpasswordpage.js +++ b/src/controllers/userpasswordpage.js @@ -47,6 +47,10 @@ define(["loading", "libraryMenu", "emby-button"], function (loading, libraryMenu } page.querySelector(".chkEnableLocalEasyPassword").checked = user.Configuration.EnableLocalPassword; + + require(["autoFocuser"], function (autoFocuser) { + autoFocuser.autoFocus(page); + }); }); }); page.querySelector("#txtCurrentPassword").value = ""; diff --git a/src/scripts/site.js b/src/scripts/site.js index b5fa85ac6..b25624add 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -477,6 +477,9 @@ var AppInfo = {}; require(["keyboardnavigation"], function(keyboardnavigation) { keyboardnavigation.enable(); }); + require(["autoFocuser"], function(autoFocuser) { + autoFocuser.enable(); + }); }); }); } @@ -858,6 +861,7 @@ var AppInfo = {}; define("serverNotifications", [componentsPath + "/serverNotifications/serverNotifications"], returnFirstDependency); define("skinManager", [componentsPath + "/skinManager"], returnFirstDependency); define("keyboardnavigation", [componentsPath + "/keyboardnavigation"], returnFirstDependency); + define("autoFocuser", [componentsPath + "/autoFocuser"], returnFirstDependency); define("connectionManager", [], function () { return ConnectionManager; });