Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable tab access to file, folder and library selectors #1153

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions www/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ iframe._invert, iframe._mwInvert {
}

#alertBoxHeader {
transition: opacity 0.5s;
text-align: center;
}

Expand Down
14 changes: 7 additions & 7 deletions www/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ <h5 class="modal-title" id="modalLabel">Modal title goes here</h5>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="collapsibleNavbar">
<ul class="navbar-nav">
<li id="liHomeNav" class="nav-item"><button type="button" data-i18n="home" class="btn btn-light" id="btnHome">Home</button></li>
<li id="liConfigureNav" class="nav-item"><button type="button" data-i18n="configure" class="btn btn-light" id="btnConfigure">Configure</button></li>
<li id="liAboutNav" class="nav-item"><button type="button" data-i18n="about" class="btn btn-light" id="btnAbout">About</button></li>
<li id="liHomeNav" class="nav-item"><button tabindex="1" type="button" data-i18n="home" class="btn btn-light" id="btnHome">Home</button></li>
<li id="liConfigureNav" class="nav-item"><button tabindex="2" type="button" data-i18n="configure" class="btn btn-light" id="btnConfigure">Configure</button></li>
<li id="liAboutNav" class="nav-item"><button tabindex="3" type="button" data-i18n="about" class="btn btn-light" id="btnAbout">About</button></li>
</ul>
</div>

Expand Down Expand Up @@ -462,7 +462,7 @@ <h2 data-i18n="configure-title">Configuration</h2>
<span id="persistentMessage"></span>
</div>
<div class="dropdown" style="float:right">
<select class="form-control" id="languageSelector" name="languageSelector" aria-labelledby="languageSelector">
<select class="form-control" tabindex="4" id="languageSelector" name="languageSelector" aria-labelledby="languageSelector">
<option data-i18n="configure-language-selector-default" selected class="dropdown-item" href="#" value="default">Language</a>
<option class="dropdown-item" href="#" value="en">English</a>
<option class="dropdown-item" href="#" value="fr">Français</a>
Expand All @@ -480,16 +480,16 @@ <h2 data-i18n="configure-title">Configuration</h2>
<p data-i18n="configure-select-instructions" id="selectInstructions">Please select or drag and drop a .zim file (or all the .zimaa, .zimab etc in
case of a split ZIM file):</p>
<span id="fileSelectionButtonContainer">
<label class="btn btn-light custom-file-upload">
<label tabindex="5" id="archiveFilesLbl" class="btn btn-light custom-file-upload">
<input type="file" id="archiveFiles" multiple class="btn"
accept="application/octet-stream,.zim,.zimaa,.zimab,.zimac,.zimad,.zimae,.zimaf,.zimag,.zimah,.zimai,.zimaj,.zimak,.zimal,.zimam,.ziman,.zimao,.zimap,.zimaq,.zimar,.zimas,.zimat,.zimau,.zimav,.zimaw,.zimax,.zimay,.zimaz,.zimba,.zimbb,.zimbc,.zimbd,.zimbe,.zimbf,.zimbg,.zimbh,.zimbi,.zimbj,.zimbk,.zimbl,.zimbm,.zimbn,.zimbo,.zimbp,.zimbq,.zimbr,.zimbs,.zimbt,.zimbu,.zimbv,.zimbw,.zimbx,.zimby,.zimbz" />
<span data-i18n="home-btn-fileselect">Select ZIM File(s)</span>
</label>
<label class="btn btn-light custom-file-upload" id="folderSelect" data-i18n="" style="display: none;" data-i18n="configure-btn-folderselect">
<label tabindex="6" class="btn btn-light custom-file-upload" id="folderSelect" data-i18n="" style="display: none;" data-i18n="configure-btn-folderselect">
<input type="file" id="archiveFolders" style="display: none;" webkitdirectory="true"/>
<span data-i18n="configure-btn-folderselect">Select Folder</span>
</label>
<label class="btn btn-light custom-file-upload" id="libraryBtn" data-i18n="configure-btn-library">
<label tabindex="7" class="btn btn-light custom-file-upload" id="btnLibrary" data-i18n="configure-btn-library">
Browse ZIM Library
</label>
</span>
Expand Down
53 changes: 41 additions & 12 deletions www/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,11 @@ if (!/^chrome-extension:/i.test(window.location.protocol)) {
}
setContentInjectionMode(params.contentInjectionMode);

// Define globalDropZone (universal drop area) and configDropZone (highlighting area on Config page)
var globalDropZone = document.getElementById('search-article');
var configDropZone = document.getElementById('configuration');
// Define frequently used UI elements
const globalDropZone = document.getElementById('search-article');
const configDropZone = document.getElementById('configuration');
const folderSelect = document.getElementById('folderSelect');
const archiveFiles = document.getElementById('archiveFiles');

// Unique identifier of the article expected to be displayed
var expectedArticleURLToBeDisplayed = '';
Expand Down Expand Up @@ -1149,7 +1151,7 @@ if (storages !== null && storages.length > 0) {
} else {
// If DeviceStorage is not available, we display the file select components
displayFileSelect();
if (document.getElementById('archiveFiles').files && document.getElementById('archiveFiles').files.length > 0) {
if (archiveFiles.files && archiveFiles.files.length > 0) {
// Archive files are already selected,
setLocalArchiveFromFileSelect();
} else {
Expand Down Expand Up @@ -1284,6 +1286,7 @@ function resetCssCache () {
}

let webKitFileList = null

/**
* Displays the zone to select files from the archive
*/
Expand Down Expand Up @@ -1346,15 +1349,15 @@ function displayFileSelect () {

if (params.isFileSystemApiSupported) {
// Handles Folder selection when showDirectoryPicker is supported
document.getElementById('folderSelect').addEventListener('click', async function (e) {
folderSelect.addEventListener('click', async function (e) {
e.preventDefault();
const previousZimFiles = await abstractFilesystemAccess.selectDirectoryFromPickerViaFileSystemApi()
if (previousZimFiles.length !== 0) setLocalArchiveFromFileList(previousZimFiles);
})
});
}
if (params.isWebkitDirApiSupported) {
// Handles Folder selection when webkitdirectory is supported but showDirectoryPicker is not
document.getElementById('folderSelect').addEventListener('change', async function (e) {
folderSelect.addEventListener('change', async function (e) {
e.preventDefault();
const filenames = [];

Expand All @@ -1374,9 +1377,10 @@ function displayFileSelect () {
await abstractFilesystemAccess.updateZimDropdownOptions(filenames, previousZimFile.length !== 0 ? lastFilename : '');
})
}

if (params.isFileSystemApiSupported) {
// Handles File selection when showOpenFilePicker is supported and uses the filesystem api
document.getElementById('archiveFiles').addEventListener('click', async function (e) {
archiveFiles.addEventListener('click', async function (e) {
e.preventDefault();
const files = await abstractFilesystemAccess.selectFileFromPickerViaFileSystemApi(e);
setLocalArchiveFromFileList(files);
Expand All @@ -1385,14 +1389,22 @@ function displayFileSelect () {
// Fallbacks to simple file input with multi file selection
useLegacyFilePicker();
}
// Add keyboard activation for folder selection
folderSelect.addEventListener('keydown', function (e) {
// We have to include e.keyCode for IE11
if (e.key === 'Enter' || e.key === ' ' || e.keyCode === 32) {
e.preventDefault();
folderSelect.click();
}
});
}

/**
* Adds a event listener to the file input to handle file selection (if no other file picker is supported)
*/
function useLegacyFilePicker () {
// Fallbacks to simple file input with multi file selection
document.getElementById('archiveFiles').addEventListener('change', async function (e) {
archiveFiles.addEventListener('change', async function (e) {
if (params.isWebkitDirApiSupported || params.isFileSystemApiSupported) {
const activeFilename = e.target.files[0].name;
localStorage.setItem('zimFilenames', [activeFilename].join('|'));
Expand All @@ -1402,6 +1414,14 @@ function useLegacyFilePicker () {
});
}

// Add keyboard selection for the archiveFiles input
document.getElementById('archiveFilesLbl').addEventListener('keydown', function (e) {
if (e.key === 'Enter' || e.key === ' ' || e.keyCode === 32) {
e.preventDefault();
archiveFiles.click();
}
});

function handleGlobalDragover (e) {
e.preventDefault();
e.dataTransfer.dropEffect = 'link';
Expand All @@ -1428,7 +1448,7 @@ async function handleFileDrop (packet) {
document.getElementById('fileSelectionButtonContainer').style.display = 'none';
document.getElementById('downloadInstruction').style.display = 'none';
document.getElementById('selectorsDisplay').style.display = 'inline';
document.getElementById('archiveFiles').value = null;
archiveFiles.value = null;

// value will be set to true if a folder is dropped then there will be no need to
// call the `setLocalArchiveFromFileList`
Expand All @@ -1444,7 +1464,8 @@ async function handleFileDrop (packet) {
if (loadZim) setLocalArchiveFromFileList(files);
}

document.getElementById('libraryBtn').addEventListener('click', function (e) {
const btnLibrary = document.getElementById('btnLibrary');
btnLibrary.addEventListener('click', function (e) {
e.preventDefault();

const libraryContent = document.getElementById('libraryContent');
Expand All @@ -1460,6 +1481,14 @@ document.getElementById('libraryBtn').addEventListener('click', function (e) {
}
});

// Add keyboard activation for library button
btnLibrary.addEventListener('keydown', function (e) {
if (e.key === 'Enter' || e.key === ' ' || e.keyCode === 32) {
e.preventDefault();
btnLibrary.click();
}
});

// Add event listener to link which allows user to show file selectors
document.getElementById('selectorsDisplayLink').addEventListener('click', function (e) {
e.preventDefault();
Expand Down Expand Up @@ -1502,7 +1531,7 @@ function archiveReadyCallback (archive) {
* Sets the localArchive from the File selects populated by user
*/
function setLocalArchiveFromFileSelect () {
setLocalArchiveFromFileList(document.getElementById('archiveFiles').files);
setLocalArchiveFromFileList(archiveFiles.files);
}
window.setLocalArchiveFromFileSelect = setLocalArchiveFromFileSelect;

Expand Down
26 changes: 22 additions & 4 deletions www/js/lib/uiUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import translateUI from './translateUI.js';
// Placeholders for the article container and the article window
const header = document.getElementById('top');
const footer = document.getElementById('footer');
const activeContent = document.getElementById('activeContent');

/**
* Hides slide-away UI elements
Expand All @@ -48,6 +49,7 @@ function hideSlidingUIElements () {
articleContainer.style.height = iframeHeight + headerHeight + 'px';
header.style.transform = 'translateY(-' + headerHeight + 'px)';
articleElement.style.transform = 'translateY(-' + headerHeight + 'px)';
hideActiveContentWarning();
}

/**
Expand Down Expand Up @@ -426,13 +428,12 @@ function deriveZimUrlFromRelativeUrl (url, base) {
*/
var activeContentWarningSetup = false;
function displayActiveContentWarning () {
var alertActiveContent = document.getElementById('activeContent');
alertActiveContent.style.display = '';
activeContent.style.display = '';
if (!activeContentWarningSetup) {
// We are setting up the active content warning for the first time
activeContentWarningSetup = true;
alertActiveContent.querySelector('button[data-hide]').addEventListener('click', function () {
alertActiveContent.style.display = 'none';
activeContent.querySelector('button[data-hide]').addEventListener('click', function () {
hideActiveContentWarning();
});
['swModeLink', 'stop'].forEach(function (id) {
// Define event listeners for both hyperlinks in alert box: these take the user to the Config tab and highlight
Expand Down Expand Up @@ -462,6 +463,21 @@ function displayActiveContentWarning () {
}
}

/**
* Hides the active content warning alert box with a fade-out effect
*/
function hideActiveContentWarning () {
const alertBoxHeader = document.getElementById('alertBoxHeader');
if (activeContent.style.display === 'none') return;
alertBoxHeader.style.opacity = 0;
alertBoxHeader.style.maxHeight = 0;
setTimeout(function () {
activeContent.style.display = 'none';
alertBoxHeader.style.opacity = 1;
alertBoxHeader.style.maxHeight = '';
}, 500);
}

/**
* Displays a Bootstrap alert box at the foot of the page to enable saving the content of the given title to the device's filesystem
* and initiates download/save process if this is supported by the OS or Browser
Expand Down Expand Up @@ -772,6 +788,8 @@ function tabTransitionToSection (toSection, isAnimationRequired = false) {
showElements(library);
}
}
// Remove any active content warning (as we will have slidden away, we don't need to use the fade out effect)
activeContent.style.display = 'none';
}

/**
Expand Down