// ==UserScript==
// @name Supercharged Local Directory File Browser
// @version 3.1.4
// @description Makes file:/// directory ("Index of...") pages (and many server-generated index pages) actually useful. Adds navigation links, file preview pane, keyboard navigation, user-defined shortcuts, filtering, more.
// @author Gaspar Schott (Michael Schrauzer) mshroud@gmail.com
// @license GPL-3.0-or-later
// @homepageURL https://openuserjs.org/scripts/gaspar_schot/Supercharged_Local_Directory_File_Browser
// @contributionURL https://paypal.me/mschrauzer
// @include file://*/
// @include file://*/?*
// @include *!localhost*/
// @require http://code.jquery.com/jquery-latest.min.js
// NOTE: By default, userscripts will not run on file:/// urls, so for this script to work, you will have to enable it in your browser extension settings.
// E.G.: For Tampermonkey in Chrome, go to Chrome the extension page, click the details button on the Tampermonkey pane and check 'Allow access to file URLs'.
// NOTE: Safari does not allow local directories to be browsed, so the script will not work on local directories, but it will work on remote directories (or on local directories through a local server).
// NOTE: This script was developed in Vivaldi, running on Mac OS Mojave. It has been tested in several other Chrome and Gecko-based browsers.
// It has been very minimally tested on Windows and not at all on other OSes or browsers. It should work, but please report any issues.
// @namespace https://greasyfork.org/users/16170
// @downloadURL none
// ==/UserScript==
(function() {
'use strict';
var $ = jQuery;
// ***** USER SETTINGS ***** //
const $settings = {
// Paste your exported settings between the two lines below:
//--------------------------------------------------------//
shortcuts: // N.B.: Directory links must end with "/", file links must end with another character.
// You may add as many menus and links as you like; just copy the example below and edit as needed.
// Local directory shortcuts must begin with "file:///"; external shortcuts must begin with the correct protocol ("http://" or "ftp://", etc.).
// Hint: you can add query strings to your urls to override user settings on a site by site basis.
// Note that because of same-origin security concerns, the browser will not allow you to navigate from an external webpage to a local directory.
// (But see this page for possible workarounds: https://stackoverflow.com/questions/39007243/cannot-open-local-file-chrome-not-allowed-to-load-local-resource)
[
{
"menu_title":"My Sample Menu",
"links":
[
{ "link_name":"My Directory Link 1", "link":"file:///Path/To/My/Directory/" },
{ "link_name":"My Directory Link 2", "link":"file:///Path/To/My/Directory_2/" },
{ "link_name":"My External Link", "link":"https://www.mywebpage.com/" },
{ "link_name":"My File Link", "link":"file:///Path/To/My/File.ext" },
]
},
{
"menu_title":"My Second Sample Menu",
"links":
[
{ "link_name":"My Directory Link 1", "link":"file:///Path/To/My/Directory/" },
{ "link_name":"My Directory Link 2", "link":"file:///Path/To/My/Directory_2/" },
{ "link_name":"My External Link", "link":"https://www.mywebpage.com/" },
{ "link_name":"My File Link", "link":"file:///Path/To/My/File.ext" },
]
},
],
UI_font: // Choose an installed font for the UI.
'lucidagrande, sans-serif',
UI_font_size: // Choose a default UI font size; use any standard CSS units.
'13px',
alternate_background: // If true (default true), alternate sidebar row background color.
true,
ignore_files: // If true (default), ignored files (see "$row_settings" below, after Keybindings and Changelog) will be greyed-out (default) in the file list and will not be loaded in the content pane when selected;
// If false, they will be treated as normal files, so if they are selected, the browser will attempt to download any file types it can't handle (which makes keyboard navigation inconvenient).
true,
hide_ignored_files: // If true, ignored files will be completely hidden from the file list;
// If false (default), ignored files will appear greyed-out.
false,
hide_invisibles: // Un*x/Mac OS only: If true (default), files or directories beginning with a "." will be hidden.
true,
hide_details: // If true (default), hide file and directory details; if false, show them.
true,
default_sort: // Choose from: 'name', 'size', 'date', 'kind', 'ext', 'default'.
// default = Chrome sorting: dirs on top, files alphabetical.
'default',
dirs_on_top: // If true, directories will always be listed firs except when sorting by "name" (since otherwise sorting by "name" would equal "default").
// If false (default), directories and files will be sorted together. (In practice, dirs will typically still be separated when sorting by size, kind, and extension.)
false,
apps_as_dirs: // Un*x/Mac OS only: if true, treat apps as directories; allows app contents to be browsed. This is the default behavior for Chrome.
// If false (default), treat apps as ignored files.
false,
dark_theme: // If true (default: false), gives the content pane a dark background, and inverts html and text content.
false,
grid_image_size: // Default = 150
150,
grid_font_size: // Default = 1
1,
autoload_media: // If true (defautl: true), the first audio or video file found in a directory will be automatically selected and loaded for playback; also, cover art (if any, will be loaded in the preview pane).
true,
autoload_index_files: // If true (default: false), automatically select first "index.ext" file found in directory.
false,
use_custom_icons: // if true (default), use custom icons for dirs and files
// if false, use browser/server default icons
true
//--------------------------------------------------------//
// Paste your exported settings between the above two lines.
}
// $ROW_TYPES:
// DO NOT DELETE ANY EXISTING CATEGORIES!
// Add file extensions for sorting and custom icon display to the existing categories.
// You can also define your own new categories, but do not add an extension to more than one row_type category.
// Do not add leading "." to the extensions.
const $row_types = {
// myCategory: ['ext1','ext2',],
dir: ['/'],
app: ['app/','app','exe','msi'],
archive: ['zip','rar','cbr','7z','tar','gz','dmg','pkg','archive'],
audio: ['mp3','m4a','aac','aif','aiff','ape','flac','ogg','wav'],
font: ['otf','ttf','woff','woff2','afm','pfb','pfm','tfm'],
graphics: ['indd','idml','indt','icml','ai','eps','pages','qxp','qxb','qxd','mif','sla','dtp','pmd','pub','fm','book','inx'],
htm: ['htm','html','xhtm','xhtml'],
image: ['jpg','jpeg','png','apng','gif','bmp','webp','svg','tif','tiff','psd','raw','dng','cr2','nef','arw'],
office: ['doc','docx','epub','xls','xlsx','xlm','odt','odf','rtf'],
pdf: ['pdf'],
text: ['txt','log','md','nfo'],
code: ['c','conf','css','h','ini','js','json','jsx','less','list','lock','php','plist','py','sass','strings','xml'],
video: ['mpeg','mov','m4v','webm','mp4'],
};
// $ROW_SETTINGS: Ignore or Exclude files by extension
const $row_settings = {
ignore: // Files with these extensions will not be loaded if selected in the sidebar (prevents the browser from attempting to download the file).
['exe','doc','docx','rtf','xls','xlsx','odt','odp','csv','msi','dll','indd','idml','pages','numbers','tif','tiff','raw','dng','cr2','nef','arw','eps','psd','ai','afm','pfb','pfm','tfm','zip','pkg','swf','pls','ics','DS_Store','ds_store','ds_store','alias','dmg','gz','qxp','icon.jpg','thumbs.db','ape','srf','epub'],
exclude: // Files with these exensions will not be inverted in dark mode
['htm','html','xhtm','xhtml'],
};
// ***** END USER SETTINGS ***** //
// KEYBINDINGS:
// Arrow Up/Down: Select prev/next item. If audio is playing, and prev/next file is also audio, it will be selected but not loaded in the audio player; press return to load it.
// Arrow Left/Right: Select prev/next row of the same kind as the current selection, except if current selection is a media file, select and begin playback of that item.
// Cmd/Ctrl + Arrow Up: Go to parent directory
// Opt/Alt + Arrow Left/Right: Skip audio ±10s
// Shift + Opt/Alt + Arrow Left/Right: Skip audio ±30s
// Space: Pause/Play media files
// Return: Open selected directory, select file, or pause/play media.
// Cmd/Ctrl + D: Toggle file details (size, date modified) in some index page types.
// Cmd/Ctrl + G: Show or Reset Grid
// Cmd/Ctrl + I: Toggle Invisibles
// Cmd/Ctrl + Shift + O: Open selected item in new window/tab
// Cmd/Ctrl + R: Reload grids and previewed content, reset scaled images/fonts, reset media files to beginning.
// Cmd/Ctrl + W: Close previewed content (doesn't work in all browsers; use close button instead), or close window if no content is being previewed.
// Cmd/Ctrl + Shift + >: Scale preview items and grids.
// CHANGELOG:
//• 3.1.4
//• FIXED: Up and down arrow navigation didn't work properly if audio and video files were present in the same directory.
//• FIXED: Prev/Next buttons in audio player weren't working.
//• FIXED: Content pane didn't resize when audio player was closed.
//• CHANGED: If autoload_media = false, don't autoload cover art when next audio track loads.
//• IMPROVED: Better support for certain server-generated index pages.
//• 3.1.3
//• FIXED: Directories weren't being sorted properly because ending "/" was being considered.
//• 3.1.2
//• FIXED: Light theme image grid items had transparent backgrounds.
//• 3.1.1
//• CHANGED: If autoload_media = false, don't select anything.
//• FIXED: Image grid columns weren't flexing to fill width.
//• 3.1.0
//• Improved font and image grid previews: added unstyled file names for clarity, file names are no longer lowercased, and dashes and underscores are replaced with spaces.
//• Various small UI tweaks.
//• 3.0.0
//• NEW: Support for video playback (finally!). Default supported video extensions: .mpeg, .mov, .m4v, .webm, .mp4 (add additional extensions below in $row_types > video).
//• IMPROVED: Cover art auto-selection: files with "back" in the name will be ignored and files with "front" or "cover" in the name will be selected.
//• IMPROVED: Directory preview styling.
//• IMPROVED: Better support for Firefox.
//• ADDED: "Autoload media" menu item.
//• CHANGED: "autoload_audio" renamed to "autoload_media"; if you export your user settings, please this update this item accordingly when you paste them back in.
//• CHANGED: Completely reworked arrow navigation and autoload_media behavior because previous behavior was confusing.
//• Up/Down Arrows will now always select the prev/next row.
//• If the audio player is not visible, it will be displayed and the selected audio file will be loaded for playback.
//• If audio is playing and the prev/next selected file is also audio, it will be selected but not loaded, so that the currently playing audio will not be interrupted. (Press return/enter to load and begin playback of selected audio.)
//• Selecting audio files deselects video files and closes video player.
//• Selecting video files deselects audio files and closes audio player.
//• Left/Right Arrows will now always select the prev/next row of the same sort kind as the currently selected file, except:
//• if the current selection is an audio file, the L/R arrows will select and begin playback of that selection.)
//• Note that if the current selection is _not_ an audio file, any currently playing audio will continue without interruption.
//• FIXED: Media files did not scroll into view when next file began playing.
//• CHANGED: Autoload cover art now works irrespective of "autoload_media" setting.
//• IMPROVED: Left/Right arrow navigation will select prev/next dir or row if there are no media, image, or font files are in the directory.
//• IMPROVED: You can now close previewed content and audio files separately from each other.
//• CHANGED: Audio file titles shown separately from other file or dir titles.
//• IMPROVED: Added string normalization for navigation by typed string: accented characters will be matched by their base ASCII letter (e.g., á = a, Ñ = n, ß = s, etc.).
//• IMPROVED: Added "other" sort category for files whose extensions are not listed in $row_types.
//• FIXED: Parent links were incorrectly formatted.
//• FIXED: Arrow buttons in preview pane were not working properly. Now, if an image or font is displayed, clicking the arrows will select the prev/next image or font file.
//• ADDED: Contact link in shortcuts menu
//• FIXED: "Donate" link.
//• Fixes for various style glitches introduced in the last version.
//• Many, many small fixes.
//• CHANGED: moved $row_types to just below user settings, for easier management and updates.
//• Internal: Reorganized, abstracted, and DRYed many functions; added more comments.
// ***** GENERAL SETUP ***** //
// ************************************ //
// DON'T EDIT ANYTHING BELOW THIS LINE. //
// ************************************ //
// Styles for iFrame Directory Index pages
if ( ( window.frameElement !== null || window.top != window.self) && window.location.href.endsWith('/') ) {
const $custom_iframe_styles = document.createElement("style");
var $iframe_styles = '';
$iframe_styles += 'a.up' +
'{ background:transparent; }';
$iframe_styles += ':root, html, body' +
'{ background-color:#BBB; }';
$iframe_styles += 'body > table > thead, body > table > tbody > tr, body ul li' +
'{ background:rgba(221,221,221,0.5); }';
$iframe_styles += 'body > table > tbody > tr:nth-of-type(odd), body > ul > li:nth-of-type(odd)' +
'{ background:rgba(221,221,221,1); }';
$iframe_styles += 'body > table > tbody > tr:hover, body > ul > li:hover:not(:first-of-type)' +
'{ background:#ABABAB; }';
$iframe_styles += ':root, html, body' +
'{ border:0 !important; }';
$iframe_styles += 'body > table' +
'{ border-top:solid 1px #888888; }';
$iframe_styles += 'body > ul > li:first-of-type' +
'{ border-bottom:solid 1px #888888; }';
$iframe_styles += 'html, body' +
'{ border-radius:0; }';
$iframe_styles += 'body > table' +
'{ border-collapse:collapse; }';
$iframe_styles += 'html, body' +
'{ box-sizing:border-box; }';
$iframe_styles += '#parentDirLinkBox span' +
'{ color:transparent; }';
$iframe_styles += 'a:hover' +
'{ color:#000000; }';
$iframe_styles += 'a, #parentDirLinkBox span:before' +
'{ color:#111111; }';
$iframe_styles += '#parentDirLinkBox span:before' +
'{ content:"Parent Directory"; }';
$iframe_styles += '#UI_goUp a.up:before' +
'{ display:none; }';
$iframe_styles += 'a, li' +
'{ display:block; }';
$iframe_styles += '#UI_goUp, #UI_showHidden' +
'{ display:inline-table; }';
$iframe_styles += 'body > table table a:before' +
'{ float:left; }';
$iframe_styles += ':root, html, body, *' +
'{ font-family:'+ $settings.UI_font +'; }';
const $font_size_units = $settings.UI_font_size.replace(/\d*/,'');
$iframe_styles += 'html, body' +
'{ font-size:'+ parseFloat($settings.UI_font_size) * 0.875 + $font_size_units +'; }';
$iframe_styles += 'body > div, body > table, thead, body p' +
'{ font-size: 1em; }';
$iframe_styles += 'body > ul > li:first-of-type, #parentDirLinkBox span:before, #UI_goUp a' +
'{ font-weight:bold; }';
$iframe_styles += 'html' +
'{ height:100%; }';
$iframe_styles += 'body' +
'{ height:auto; }';
$iframe_styles += '#UI_goUp, #UI_showHidden, #UI_showHidden label' +
'{ height:1.5em !important; }';
$iframe_styles += 'body > table > tbody > tr, body > ul > li' +
'{ line-height:1.5; }';
$iframe_styles += '#UI_goUp, #UI_showHidden' +
'{ line-height:2; }';
$iframe_styles += 'body > ul' +
'{ list-style:none; }';
$iframe_styles += 'html, body, body div, body > ul > li a, #UI_goUp, #UI_showHidden, #parentDirLink, #parentDirLinkBox' +
'{ margin:0; }';
$iframe_styles += 'body > div' +
'{ margin:1em; }';
$iframe_styles += 'body p' +
'{ margin:1rem; }';
$iframe_styles += 'body > ul > li' +
'{ margin-bottom:0; }';
$iframe_styles += '.up' +
'{ margin-inline-start:0; }';
$iframe_styles += '.dir::before, .file > img' + // firefox
'{ margin-inline-end: 6px; }';
$iframe_styles += ':root, html, body, body > div, body > ul > li, .up' +
'{ padding:0; }';
$iframe_styles += 'body > table > tbody > tr > td, body > table > thead > tr > th, body > ul > li a, #parentDirLinkBox, #UI_goUp, #UI_showHidden' +
'{ padding-top:3px; }';
$iframe_styles += 'body > table > tbody > tr > td:first-of-type, body > table > thead > tr > th:first-of-type, body > ul > li a' +
'{ padding-right:0; }';
$iframe_styles += 'body > table th:last-of-type, body > table > tbody > tr > td:last-of-type, body > ul > li a, #parentDirLinkBox, #UI_showHidden' +
'{ padding-right:1em; }';
$iframe_styles += '#parentDirLinkBox' +
'{ padding-bottom:0; }';
$iframe_styles += 'body > table > tbody > tr > td, body > table > thead > tr > th, body > ul > li a, #parentDirLinkBox, #UI_goUp, #UI_showHidden' +
'{ padding-bottom:3px; }';
$iframe_styles += 'body > ul' +
'{ padding-left:0; }';
$iframe_styles += 'body > table > tbody > tr > td:first-of-type, body > table > thead > tr > th:first-of-type, body > ul > li a, #parentDirLinkBox, #UI_goUp' +
'{ padding-left:1em; }';
$iframe_styles += 'th:not(:first-of-type)' +
'{ text-align:right; }';
$iframe_styles += 'th:first-of-type' +
'{ text-align:left; }';
$iframe_styles += 'a, a:hover, td:hover, li:hover' +
'{ text-decoration:none !important; }';
$iframe_styles += 'a.icon' +
'{ text-indent:2px; }';
$iframe_styles += '#UI_goUp, #UI_showHidden' +
'{ vertical-align:middle; }';
$iframe_styles += 'html, body, body > table' +
'{ width:100%; }';
$iframe_styles += 'thead th:first-of-type' +
'{ width:50%; }';
$iframe_styles += 'html, body' +
'{ max-width:100%; }';
$iframe_styles += 'html, body' +
'{ min-width:100%; }';
$iframe_styles += 'body table tr, body ul li, body > table > tbody > tr:hover' +
'{ outline:0; }';
$('body').css({'font-family':$settings.UI_font});
$('body > h1, address, body > hr').remove();
$('body > table > tbody').find('hr').closest('tr').remove();
$('body > table th:contains("Name")').css({'text-align':'left'});
$('body > table th:contains("Size")').css({'text-align':'right'});
// pre type
if ( $('body > pre').length ) {
let $list_items = $('body pre').html();
let $parent_dir = $('body pre').find('a:contains("Parent")').first().attr('href');
$list_items = '
');
const $sample_string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 [(!@#$%^&*;:)]';
const $lorem_string = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';
const $specimen = $('