Supercharged Local Directory File Browser

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.

目前为 2018-04-03 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Supercharged Local Directory File Browser
  3. // @version 2.0.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.
  5. // @author Gaspar Schott
  6. // @license GPL-3.0
  7. // @match file:///*
  8. // @require http://code.jquery.com/jquery-latest.min.js
  9.  
  10. // This script was developed in Vivaldi, running on Mac OS High Sierra. It has been tested in various Chrome and Gecko-based browsers. It has only been minimally tested on Windows, however. It should work, but please report any issues.
  11. // It does not work in Safari because Safari does not allow local directories to be browsed.
  12.  
  13. // NOTE: By default, Greasemonkey and Tampermonkey will not run scripts on file:/// urls, so for this script to work, you will have to enable it first.
  14. // For Greasemonkey, open about:config and change greasemonkey.fileIsGreaseable to true.
  15. // For Tampermonkey, go to Chrome extension page, and tick the 'Allow access to file URLs' checkbox at the Tampermonkey extension section.
  16.  
  17. // CHANGELOG:
  18.  
  19. // v. 2.0.1
  20. // Fixed wonky font preview scaling.
  21.  
  22. // v. 2.0
  23. // NEW! Not just for local directories anymore! Added support for *many* server-generated directory index pages (It's impossible to check every server configuration, needless to say, so it might not work in every case; let me know if you encounter problems.// NEW! Preview font files (otf, ttf, woff, woff2). Great for designers: preview fonts without installing them. Hint: To install previewed fonts, just type Cmd/Ctrl + O or right-click the link and save it to your fonts folder. Font preview pane is content-editable.
  24. // NEW! Preview font files (otf, ttf, woff, woff2). Great for designers: preview fonts without installing them. Hint: To install previewed fonts, just type Cmd/Ctrl + Shift + O or right-click the link and save it to your fonts folder. Font preview pane is content-editable.
  25. // Added: Now use the Left and Right arrow keys to navigate through images and fonts in a folder, skipping other files. Use up and down arrow keys to navigate all files normally.
  26. // Added: Basic dark mode user setting.
  27. // Added: Wrap-around keyboard navigation.
  28. // Added: Cmd/Ctr-D to toggle details.
  29. // Added: Cmd/Ctr-Shift-. and Cmd/Ctr-Shift-, to scale font previews text size.
  30. // Changed: Moved dynamically-added in-line styles to appended stylesheet.
  31. // Changed: Extensive refactoring of code for better separation of concerns. (More needs to be done.... Sigh.)
  32. // Removed: ScrollIntoView for Grid views. Scrolling didn't work reliably when the sidebar was also being scrolled. Will restore when bug fixed.
  33. // Many small bug fixes.
  34.  
  35. // v. 1.4
  36. // Added: Initial support for Firefox. Tested in Firefox 59, Waterfox 56.
  37. // Changed: Use SVG for menu icons
  38. // Changed: Code cleanup, reorganization
  39. // Renamed script to "Supercharged Local Directory File Browser"
  40.  
  41. // v. 1.3
  42. // Fixed: Keyboard navigation of ignored or invisible items fails if "Hide Invisibles" is toggled off after loading a directory.
  43. // Added: Also hide ignored files if "Hide Invisibles" is checked.
  44. // Added: Content reload button.
  45. // Changed: Reorganized settings to reduce confusion about how ignored files are treated.
  46.  
  47. // v. 1.2
  48. // Click to show menus instead of hover.
  49. // Added Cmd/Crl+Shift+O keybinding to open selected item in new window
  50. // Arrow navigation bugfixes
  51.  
  52. // TO-DO:
  53. // Select two items for split pane view?
  54. // if invisible item is selected when "hide invisibles" is unchecked, select nearest previous visible item when hide invisible is checked agagin?
  55.  
  56. // @namespace https://greasyfork.org/users/16170
  57. // ==/UserScript==
  58.  
  59. (function() {
  60. 'use strict';
  61. var $ = jQuery;
  62.  
  63. // ***** USER SETTINGS ***** //
  64.  
  65. var $settings = {
  66.  
  67. user_name: // Your computer user name
  68. 'MacBookPro',
  69. // Shortcuts: add directories and files here. (You can use your browser's bookmarks, of course.)
  70. root_shortcuts: // Root directories: add or remove as you please (but at leave empty brackets). These defaults are applicable to Mac OS.
  71. ['Applications','Library','Users','Volumes'],
  72. // ['C:/Users','C:/Program Files','C:/Windows'],
  73. user_shortcuts: // User directories; you must enter your user_name above.
  74. ['Documents','Downloads','Library','Movies','Music','Pictures'],
  75. file_shortcuts: // Add specific file paths, e.g.: 'Users/MyUserName/Documents/MyDocument.html'
  76. // These files will be selected (loaded) automatically when their containing directory is loaded
  77. // Limitations: only works for one file per directory; if more than one file per directory is listed, the last item will be selected.
  78. ['path/to/file.ext','path/to/another/file.ext'],
  79. ignore_files: // If true, ignored files (see below) will be greyed-out (default) in the file list and will not be loaded in the content pane when selected;
  80. // 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).
  81. true,
  82. ignore_file_types: // ignore files with these extensions:
  83. ['exe','.doc','.docx','ppt','pptx','xls','xlsx','odt','odp','.csv','msi','dll','rtf','indd','idml','.pages','.tif','tiff','.eps','.psd','.ai','.afm','.pfb','.pfm','.tfm','.zip','pkg','.swf','.pls','.ics','.ds_store','ds_store','alias','.dmg','.gz','.qxp','icon.jpg','thumbs.db'], // lowercase
  84. hide_ignored_files: // If true, ignored files will be hidden in the file list;
  85. // if false, they will appear greyed-out (default).
  86. false,
  87. hide_invisibles: // Mac OS only: If true, files or directories beginning with a "." will be hidden.
  88. true,
  89. apps_as_dirs: // Mac OS only: if true, treat apps as directories; allows app contents to be browsed. This is the default behavior for Chrome.
  90. // If false, treat apps as ignored files.
  91. false,
  92. dark_mode: // If true, gives the content pane a dark background, and inverts html and text content.
  93. // For more fine-grained control, set this to false and install this user style instead:
  94. false
  95. };
  96.  
  97. // ***** END USER SETTINGS ***** //
  98.  
  99. // ***** SETUP ***** //
  100.  
  101. var $userAgent = navigator.userAgent;
  102.  
  103. function platformIsMac() {
  104. return navigator.platform.indexOf('Mac') > -1;
  105. }
  106. function platformIsWin() {
  107. return navigator.platform.indexOf('Win') > -1;
  108. }
  109. // Don't run script in iframes or files (only directories)
  110. // if ( window.top != window.self ) {
  111. if ( window.frameElement !== null ) {
  112. return;
  113. }
  114. if ( window.location.pathname.slice(-1) != '/') {
  115. return;
  116. }
  117.  
  118. var $body = $('body');
  119. // add lang attr, remove some unneeded default elements
  120. $body.attr('lang','en').find('> h1:contains("Index of"),> #parentDirLinkBox,> #UI_goUp,#UI_showHidden').remove();
  121.  
  122. var $location = window.location.pathname;
  123. var $current_dir_path = $location.replace(/%20/g,' ').replace(/\//g,'/<wbr>').replace(/_/g,'_<wbr>').replace(/—/g,'—<wbr>').replace(/\\/g,'/');
  124. var $current_dir_name = $location.replace(/%20/g,' ').slice(0,-1);
  125. $current_dir_name = $current_dir_name.slice($current_dir_name.lastIndexOf('/') + 1);
  126. var $location_arr = $location.split('/');
  127. var $parent_dir_link = $location_arr.slice(0,-2).join('/') + '/';
  128.  
  129. var e, i, n;
  130. var $this_link;
  131.  
  132. var $dir_table;
  133. var $dir_table_type;
  134. var $dir_table_head;
  135. var $dir_table_head_cell;
  136. var $dir_table_head_name;
  137. var $dir_table_head_details;
  138. var $dir_table_body;
  139. var $dir_table_row;
  140. var $dir_table_cell;
  141. var $dir_table_item_name;
  142. var $dir_table_details;
  143. var $dir_table_item_icon;
  144. var $dir_table_link;
  145. var $dir_table_rule;
  146. var $selected;
  147.  
  148. if ( $body.find('> table').length > 0 ) {
  149. $dir_table = $body.find('> table');
  150. $dir_table.addClass('table');
  151. } else {
  152. $dir_table = $body.find('> ul');
  153. $dir_table.add('body').addClass('list');
  154. }
  155.  
  156. // ***** BUILD UI ELEMENTS ***** //
  157.  
  158. // ***** SIDEBAR ELEMENTS ***** //
  159.  
  160. // 1. Parent Directory Menu
  161. var $parent_dir_menu = $('<nav id="parent_dir_menu"><a href="">&nbsp;</a></nav>');
  162. $parent_dir_menu.find('a').attr('href',$parent_dir_link);
  163. // 2. Current Directory Name and Parents Directory Menu
  164. var $parents_dir_menu = $('<nav id="parents_dir_menu"><div></div></nav><ul class="menu"></ul>');
  165. $parents_dir_menu.find('div').append( $current_dir_path );
  166. // 3. Shortcuts Menu
  167. var $divider = $('<li><hr></li>');
  168. var $shortcuts_menu = $('<nav id="shortcuts_menu"><div>&nbsp;</div></nav><ul class="menu"></ul>');
  169. // 4. Details Button
  170. var $details_btn = $('<button id="details_btn" tabindex="-1"><span>Show details</span><span>Hide details</span></button>');
  171. // 5. Invisibles Checkbox
  172. var $inv_checkbox = $('<label ><input type="checkbox" id="inv_checkbox" for="inv_checkbox" name="inv_checkbox" tabindex="-1" />Hide Invisibles</label>');
  173. // 6. Image Grid Button
  174. var $grid_btn = $('<div id="grid_btn" tabindex="-1" title="Show Grid"><ul class="menu"><li id="show_image_grid">Show Image Grid</li><li id="show_font_grid">Show Font Grid</li></ul></div>');
  175. // 7. Sidebar Header Element
  176. var $sidebar_header = $('<table id="sidebar_header"><thead><tr><th colspan="3">INDEX OF</th></tr></thead><tbody><tr><td></td><td></td><td></td></tr><tr><td colspan="3"></td></tr></tbody></table>');
  177. $sidebar_header.find('tbody tr:nth-child(1)').find('td').first().append( $parent_dir_menu ).next().append( $parents_dir_menu ).next().append( $shortcuts_menu );
  178. $sidebar_header.find('tbody tr:last-child td').append( $details_btn, $inv_checkbox, $grid_btn );
  179.  
  180. var $dir_table_wrapper = $('<div id="dir_table_wrapper"></div>');
  181. // 8. Sidebar
  182. var $sidebar = $('<div id="sidebar"></div>');
  183. $sidebar.append($sidebar_header);
  184. // 9. Resize Handle
  185. var $handle = $('<div id="handle"></div>');
  186. // 10. Assemble Sidebar Elements
  187. var $sidebar_wrapper = $('<td id="sidebar_wrapper"></td>');
  188. $sidebar_wrapper.append( $sidebar, $handle );
  189.  
  190. // ***** END SIDEBAR ELEMENTS ***** //
  191.  
  192. // ***** CONTENT PANE ELEMENTS ***** //
  193.  
  194. // 1. Reload Button Element
  195. var $content_reload_btn = $('<td><button id="reload_btn" tabindex="-1">Reload</button></td>');
  196. // 2. Title Element
  197. var $content_title = $('<td id="content_title"></td>');
  198. // 3. Close Button Element
  199. var $content_close_btn = $('<td><button id="close_btn" tabindex="-1">Close</button></td>');
  200. // 4. Content Header Element
  201. var $content_header = $('<header id="content_header"><table><tbody><tr></tr></tbody></table></header>');
  202. $content_header.find('tr').append($content_reload_btn, $content_title, $content_close_btn);
  203. // 5. Content Mask Element
  204. var $content_mask = $('<div id="content_mask""></div>');
  205. // 6. Image Grid Element
  206. var $content_grid = $('<div id="content_grid"></div>');
  207. // 7. Content grid items
  208. var $image_grid_item_el = $('<div class="image_grid_item"><a href=""><img src="" /></a></div>');
  209. var $font_grid_item_el = $('<div class="font_grid_item"></div>');
  210. var $content_font_size = $('<div id="font_size"><span id="increase"></span><span id="decrease"></span></div>');
  211. // 8. Image Element
  212. var $image = $('<img class="" />');
  213. var $content_image = $('<div id="content_image"></div>');
  214. $content_image.append($image);
  215. // 9. Pdf (embed) Element
  216. var $content_embed = $('<embed id="content_embed" name="plugin" type="application/pdf" tabindex="0"></embed>');
  217. // 10. Iframe Element
  218. var $content_iframe = $('<iframe id="content_iframe" sandbox="allow-scripts allow-same-origin allow-modals" tabindex="0"></iframe>');
  219. // 11. Font Element
  220. var $sample_string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ<br />abcdefghijklmnopqrstuvwxyz<br />0123456789 [(!@#$%^&*;:)]';
  221. var $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.';
  222. var $specimen;
  223. function specimen() {
  224. var $specimen_arr = [];
  225. for ( i = 0; i < 4; i+=1 ) {
  226. $specimen = '<div class="specimen" style="font-size:'+ (i * 12) +'pt;">'+ $sample_string +'</div><div class="lorem" style="font-size:'+ (i * 6) +'pt;">'+ $lorem_string +'</div><div class="lorem" style="font-size:'+ (i * 6) +'pt;">'+ $lorem_string +'</div><div class="lorem" style="font-size:'+ (i * 6) +'pt;">'+ $lorem_string +'</div>';
  227. $specimen_arr.push($specimen);
  228. }
  229. $specimen_arr = $specimen_arr.reverse().join().replace(/,/g,'');
  230. return $specimen_arr;
  231. }
  232. // Use specimen() in $content_font in place of $specimen for 5 different sizes of $sample_string.
  233. $specimen = '<div class="specimen" style="font-size:3em;">'+ $sample_string +'</div><div class="lorem" style="font-size:1em;">'+ $lorem_string +'</div><div class="lorem" style="font-size:1em;">'+ $lorem_string +'</div><div class="lorem" style="font-size:1em;">'+ $lorem_string +'</div>';
  234. var $lorem = $('.lorem');
  235. var $content_font = $('<div id="content_font" spellcheck="false" contenteditable="true">'+ $specimen +'</div>');
  236.  
  237. // 12. Next/Prev Elements
  238. var $prev_btn = $('<div id="prev_btn"></div>');
  239. var $next_btn = $('<div id="next_btn"></div>');
  240. // 13. Content container
  241. var $content_container = $('<section id="content_container"></section>');
  242. $content_container.append( $content_header, $content_font_size, $content_mask, $content_grid, $content_image, $content_embed, $content_iframe, $content_font );
  243.  
  244. // 14. Assemble Content Pane Elements
  245. var $content_pane = $('<td id="content_pane"></td>');
  246. $content_pane.append( $content_container, $prev_btn, $next_btn );
  247.  
  248. // ***** END BUILD UI ELEMENTS ***** //
  249.  
  250. // ***** STYLES ***** //
  251.  
  252. var $custom_font_styles = document.createElement('style');
  253. $custom_font_styles.appendChild(document.createTextNode(""));
  254. document.head.append($custom_font_styles);
  255.  
  256. var $font_styles = '';
  257. $custom_font_styles.append( $font_styles );
  258.  
  259. var $custom_styles = document.createElement("style");
  260. $custom_styles.appendChild(document.createTextNode(""));
  261.  
  262. var $up_arrow = 'url("data:image/svg+xml;utf8,<svg version=\'1.1\' id=\'Layer_1\' xmlns=\'http://www.w3.org/2000/svg\' xmlns:xlink=\'http://www.w3.org/1999/xlink\' x=\'0px\' y=\'0px\' width=\'12.728px\' height=\'7.779px\' viewBox=\'0 0 12.728 7.779\' enable-background=\'new 0 0 12.728 7.779\' xml:space=\'preserve\'><path fill=\'%23444444\' d=\'M6.364,2.828l4.95,4.949l1.414-1.414L6.364,0l0,0L0,6.363l1.413,1.416L6.364,2.828\'/></svg>")';
  263. var $svg_arrow = 'url("data:image/svg+xml;utf8,<svg version=\'1.1\' id=\'Layer_1\' xmlns=\'http://www.w3.org/2000/svg\' xmlns:xlink=\'http://www.w3.org/1999/xlink\' x=\'0px\' y=\'0px\' width=\'11px\' height=\'16px\' viewBox=\'234.5 248 11 16\' enable-background=\'new 234.5 248 11 16\' xml:space=\'preserve\'><path d=\'M245.5,261l-3,3l-8-8l8-8l3,3l-5,5L245.5,261z\'/></svg>")';
  264. var $menu_icon = 'url("data:image/svg+xml;utf8,<svg version=\'1.1\' id=\'Layer_1\' xmlns=\'http://www.w3.org/2000/svg\' xmlns:xlink=\'http://www.w3.org/1999/xlink\' x=\'0px\' y=\'0px\' width=\'13px\' height=\'10px\' viewBox=\'0 0 13 10\' enable-background=\'new 0 0 13 10\' xml:space=\'preserve\'><rect fill=\'%23444444\' width=\'13\' height=\'2\'/><rect y=\'4\' fill=\'%23444444\' width=\'13\' height=\'2\'/><rect y=\'8\' fill=\'%23444444\' width=\'13\' height=\'2\'/></svg>")';
  265. var $grid_icon = 'url("data:image/svg+xml;utf8,<svg version=\'1.1\' id=\'Layer_1\' xmlns=\'http://www.w3.org/2000/svg\' xmlns:xlink=\'http://www.w3.org/1999/xlink\' x=\'0px\' y=\'0px\' width=\'16px\' height=\'16px\' viewBox=\'0 0 16 16\' enable-background=\'new 0 0 16 16\' xml:space=\'preserve\'><g><path fill=\'%23666666\' d=\'M5,2v3H2V2H5 M7,0H0v7h7V0L7,0z\'/></g><g><path fill=\'%23666666\' d=\'M14,2v3h-3V2H14 M16,0H9v7h7V0L16,0z\'/></g><g><path fill=\'%23666666\' d=\'M5,11v3H2v-3H5 M7,9H0v7h7V9L7,9z\'/></g><g><path fill=\'%23666666\' d=\'M14,11v3h-3v-3H14 M16,9H9v7h7V9L16,9z\'/></g></svg>")';
  266. var $plus_sign = 'url("data:image/svg+xml;utf8,<svg version=\'1.1\' baseProfile=\'basic\' id=\'Layer_1\' xmlns=\'http://www.w3.org/2000/svg\' xmlns:xlink=\'http://www.w3.org/1999/xlink\' x=\'0px\' y=\'0px\' width=\'16px\' height=\'16px\' viewBox=\'0 0 16 16\' xml:space=\'preserve\'><polygon points=\'16,6.5 9.5,6.5 9.5,0 6.5,0 6.5,6.5 0,6.5 0,9.5 6.5,9.5 6.5,16 9.5,16 9.5,9.5 16,9.5 \'/></svg>")';
  267. var $minus_sign = 'url("data:image/svg+xml;utf8,<svg version=\'1.1\' baseProfile=\'basic\' id=\'Layer_1\' xmlns=\'http://www.w3.org/2000/svg\' xmlns:xlink=\'http://www.w3.org/1999/xlink\' x=\'0px\' y=\'0px\' width=\'16px\' height=\'16px\' viewBox=\'0 0 16 16\' xml:space=\'preserve\'> <rect x=\'1\' y=\'6.499\' width=\'14\' height=\'3.001\'/> </svg>")';
  268.  
  269. var $styles = '';
  270.  
  271. $styles += 'html, body, :root { margin:0; padding:0; max-width:100%; height:100%; font-family:lucidagrande,"fira sans",helvetica,sans-serif; font-size:13px !important; hyphens:auto; overflow:hidden; border-radius:0; box-sizing:border-box; }';
  272. $styles += 'ul { -webkit-margin-before:0em !important; -webkit-margin-after:0em !important; -webkit-padding-start:0em; }';
  273. $styles += 'hr { margin:0; border-bottom:0; }';
  274.  
  275. // SIDEBAR
  276. $styles += '#sidebar_wrapper { width:25%; min-width:220px; will-change:width; padding:0; position:relative; border:0; background:lightgray; overflow:hidden; }';
  277. $styles += '#sidebar { background-color:lightgray; height:'+ window.innerHeight +'px; min-height:100%; overflow-wrap:break-word; box-sizing:border-box; border-right:solid 1px gray; font-size:0.875em; color:#333; overflow:hidden; }';
  278. $styles += '#handle { width:8px; position:absolute; top:0; right:-4px; bottom:0; z-index:1000; cursor:col-resize; }';
  279.  
  280. // Sidebar Header
  281. $styles += '#sidebar_header { width:100%; height:auto; position:relative; border:0; user-select:none; border-collapse:collapse; font-size:0.875rem; }';
  282. $styles += '#sidebar_header thead tr, #sidebar_header tbody tr:first-of-type { border-bottom:solid 1px grey; background-color:#BBB; }';
  283. $styles += '#sidebar_header thead th { padding:4px; font-weight:normal; font-size:0.875em; letter-spacing:0.5em; cursor:default; }';
  284. $styles += '#sidebar_header tbody tr { position:relative; }';
  285. $styles += '#sidebar_header tbody tr:first-of-type td:hover { cursor:pointer; }';
  286. $styles += '#sidebar_header tbody tr:first-of-type td:nth-of-type(odd) { width:24px; max-width:24px; min-width:24px; padding:0; }';
  287. $styles += '#sidebar_header tbody tr:first-of-type td:nth-of-type(even) { width:100%; padding:0; border-left:solid 1px grey; border-right:solid 1px grey; }';
  288. $styles += '#sidebar_header tbody tr:last-of-type td { padding:1em 0; vertical-align:middle; position:relative; white-space:normal; }';
  289.  
  290. // Menus
  291. $styles += '#parent_dir_menu { width:100%; height:auto; margin:0; padding:0; display:table; }';
  292. $styles += '#parent_dir_menu a { width:100%; height:100%; padding:0; display:table-cell; text-align:center; vertical-align:middle; text-decoration:none; opacity:0.7; background:' + $up_arrow + 'center no-repeat; }';
  293.  
  294. $styles += '#parents_dir_menu { margin:0; padding:0; height:auto; text-align:center; }';
  295. $styles += '#parents_dir_menu div { padding:4px 6px; height:auto; display:inline-block; text-align:center; vertical-align:middle; overflow:hidden; cursor:pointer; hyphens:none; white-space:normal; }';
  296. $styles += '#parents_dir_menu + ul { display:none; margin:0; padding:0; position:absolute; right:0; left:0; z-index:100; text-indent:0; text-align:left; background:lightgray; border-top:solid 1px gray; border-bottom:solid 1px gray; list-style-type:none; box-shadow: 0px 2px 3px -2px #888; }';
  297. $styles += '#parents_dir_menu + ul li:hover, #shortcuts_menu + ul li:hover { background:#BBB; }';
  298. $styles += '#parents_dir_menu + ul li a, #shortcuts_menu + ul li a { margin:0; padding:4px 6px; display:block; text-indent:0; text-decoration:none; color:#333; white-space:normal; }';
  299.  
  300. $styles += '#shortcuts_menu { margin:0; padding:0; }';
  301. $styles += '#shortcuts_menu div { width:6em; display:table-cell; text-align:center; vertical-align:middle; font-size:18px; cursor:pointer; opacity:0.7; background:'+ $menu_icon + 'center no-repeat; }';
  302. $styles += '#shortcuts_menu + ul { margin:0; padding:0; -webkit-margin-before:0em !important; -webkit-margin-after:0em !important; -webkit-padding-start:0em; position:absolute; right:0; left:0; z-index:100; text-indent:0; text-align:left; background:lightgray; border-top:solid 1px gray; border-bottom:solid 1px gray; list-style-type:none; box-shadow: 0px 2px 3px -2px #888; display:none; }';
  303. $styles += '#shortcuts_menu div, #parent_dir_menu, #prev_btn, #next_btn { opacity:0.7; }';
  304.  
  305. // Details Button
  306. $styles += '#details_btn { margin:0 0.5em; }';
  307. $styles += '#details_btn span:last-of-type { display:none; }';
  308. $styles += 'body.list #details_btn { color:#999; background:#EEE; outline:none; }';
  309.  
  310. // Grid Button
  311. $styles += '#grid_btn { margin:0; width:28px; height:18px; display:none; float:right; cursor:pointer; outline:0; background:'+ $grid_icon +' no-repeat center 100%; }';
  312. $styles += '#grid_btn ul.menu { margin-right:28px; position:absolute; top:0; right:0; display:none; }';
  313. $styles += '#grid_btn ul.menu li { width:100%; padding:4px 6px; background:#CCC; display:block; float:right; clear:both; text-align:right; list-style:none; box-sizing:border-box; }';
  314. $styles += '#grid_btn:hover, #shortcuts_menu div:hover, #parent_dir_menu:hover, #prev_btn:hover, #next_btn:hover { opacity:1; }';
  315. $styles += '#grid_btn.has_images, #grid_btn.has_fonts { display:inline-block; }';
  316. $styles += '#grid_btn.has_images.has_fonts:hover ul.menu { display:block !important; }';
  317. $styles += '#grid_btn.has_images.has_fonts:hover ul.menu li:hover { background:#BBB; }';
  318.  
  319. // Sidebar dir_table
  320. $styles += '#dir_table.table { width:100%; min-wdth:100px; border:0; position:relative; overflow:hidden; table-layout:fixed; border-collapse:collapse; font-size:0.875rem; }';
  321. $styles += '#dir_table.table thead { width:100%; position:absolute; left:0; right:0; text-align:left; }';
  322. $styles += '#dir_table.table thead th { padding:0 24px 4px; }';
  323. $styles += '#dir_table.table thead .name { padding-left:2em; display:block; }';
  324. $styles += '#dir_table.table > tbody { width:100%; position:absolute; right:0; bottom:0; left:0; overflow-y:auto; outline:0; }';
  325. $styles += '#dir_table.table.headless > tbody { top:0 !important; }';
  326. $styles += '#dir_table.table tbody .name { display:block; clear:right; text-align:left; }';
  327. $styles += '#dir_table.table tbody tr { display:block; margin-inline-start:0; clear:both; }';
  328. $styles += '#dir_table.table tbody a { margin:0; display:block; background-size:auto 13px; -webkit-padding-start:2m; padding: 4px 6px 4px 24px; color:#333; text-decoration:none; outline:none; overflow:hidden; background-position:6px 4px; white-space:normal; }';
  329. $styles += '#dir_table.table #thead .name a { padding:0; }';
  330. $styles += '#dir_table.table.headless .icon { vertical-align:middle; float:left; }';
  331. $styles += '#dir_table.table .icon img { margin-left:1rem; height:16px; }';
  332. $styles += '#dir_table.table .icon + td.name a { -webkit-padding-start:1em; padding-left:6px; }';
  333. $styles += '#dir_table.table .details, #dir_table.table.firefox #tbody > tr > td:not(:first-of-type) { display:none; padding:0 0 4px 24px; font-size:0.875em; text-align:left; vertical-align:top; float:left; }';
  334. $styles += '#dir_table.table.firefox #tbody > tr > td:not(:first-of-type) { padding:0 24px 4px; }';
  335. $styles += '#dir_table.table.firefox #tbody > tr > td:last-of-type { text-indent:6px; }';
  336. $styles += '#dir_table.table .details a { padding:0; }';
  337. $styles += '#dir_table.table .rule { display:none; }';
  338. $styles += '#dir_table.table.show_details .details, #dir_table.table.firefox.show_details #tbody > tr > td:not(:first-of-type) { display:block; }';
  339.  
  340. // dir_table.list
  341. $styles += '#dir_table_wrapper { width:100%; min-width:100px; border:0; position:relative; overflow-y:auto; }';
  342. $styles += '#dir_table.list #dir_table_wrapper { padding-top:6px; }';
  343. $styles += '#dir_table.list { width:100%; position:absolute; overflow-y:auto; list-style:none; -webkit-margin-before:0; -webkit-margin-after:0; -webkit-padding-start:0; font-size:0.875rem; line-height:1.4; }';
  344. $styles += '#dir_table.list li a { display:block; padding:3px 1rem; text-decoration:none; color:#333; }';
  345. $styles += '#dir_table.list li.dir a { padding-left:24px; background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAd5JREFUeNqMU79rFUEQ/vbuodFEEkzAImBpkUabFP4ldpaJhZXYm/RiZWsv/hkWFglBUyTIgyAIIfgIRjHv3r39MePM7N3LcbxAFvZ2b2bn22/mm3XMjF+HL3YW7q28YSIw8mBKoBihhhgCsoORot9d3/ywg3YowMXwNde/PzGnk2vn6PitrT+/PGeNaecg4+qNY3D43vy16A5wDDd4Aqg/ngmrjl/GoN0U5V1QquHQG3q+TPDVhVwyBffcmQGJmSVfyZk7R3SngI4JKfwDJ2+05zIg8gbiereTZRHhJ5KCMOwDFLjhoBTn2g0ghagfKeIYJDPFyibJVBtTREwq60SpYvh5++PpwatHsxSm9QRLSQpEVSd7/TYJUb49TX7gztpjjEffnoVw66+Ytovs14Yp7HaKmUXeX9rKUoMoLNW3srqI5fWn8JejrVkK0QcrkFLOgS39yoKUQe292WJ1guUHG8K2o8K00oO1BTvXoW4yasclUTgZYJY9aFNfAThX5CZRmczAV52oAPoupHhWRIUUAOoyUIlYVaAa/VbLbyiZUiyFbjQFNwiZQSGl4IDy9sO5Wrty0QLKhdZPxmgGcDo8ejn+c/6eiK9poz15Kw7Dr/vN/z6W7q++091/AQYA5mZ8GYJ9K0AAAAAASUVORK5CYII= ") 6px 4px no-repeat; background-size:auto 13px; }';
  346. $styles += '#dir_table.list li.file a { padding-left:24px; background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABnRSTlMAAAAAAABupgeRAAABHUlEQVR42o2RMW7DIBiF3498iHRJD5JKHurL+CRVBp+i2T16tTynF2gO0KSb5ZrBBl4HHDBuK/WXACH4eO9/CAAAbdvijzLGNE1TVZXfZuHg6XCAQESAZXbOKaXO57eiKG6ft9PrKQIkCQqFoIiQFBGlFIB5nvM8t9aOX2Nd18oDzjnPgCDpn/BH4zh2XZdlWVmWiUK4IgCBoFMUz9eP6zRN75cLgEQhcmTQIbl72O0f9865qLAAsURAAgKBJKEtgLXWvyjLuFsThCSstb8rBCaAQhDYWgIZ7myM+TUBjDHrHlZcbMYYk34cN0YSLcgS+wL0fe9TXDMbY33fR2AYBvyQ8L0Gk8MwREBrTfKe4TpTzwhArXWi8HI84h/1DfwI5mhxJamFAAAAAElFTkSuQmCC") 6px 4px no-repeat; background-size:auto 13px; }';
  347.  
  348. $styles += '#dir_table tr, #dir_table li { background:transparent; }';
  349. $styles += '#dir_table tr:hover, #dir_table li:hover, #dir_table .hovered { background:#BBB; }';
  350.  
  351. $styles += '#dir_table tr.selected, #dir_table li.selected { background:lightsteelblue; }';
  352. $styles += '#dir_table tr.selected a, #dir_table li.selected a { font-weight:bold; color:#333; }';
  353. $styles += 'body.blur_sidebar tr.selected { background-color:#BBB; }';
  354. $styles += 'body.blur_sidebar tr.selected a { font-weight:normal; color:#444; }';
  355.  
  356. $styles += '#dir_table tr.ignore a, #dir_table tr.ignore.app a { color:#888; }';
  357. $styles += '#dir_table.hide_invisibles .invisible { display:none !important; }';
  358. $styles += '#dir_table.hide_ignored tr.ignore { display:none !important; }';
  359.  
  360. // CONTENT PANE
  361. $styles += '#content_pane { width:75%; will-change:width; padding:0; border:0; background:#FFF; position:relative; }';
  362. $styles += '#content_container { width:100%; height:100%; top:0; overflow:visible; }';
  363.  
  364. // Content pane header
  365. $styles += '#content_header { width:100%; display:none; position:absolute; top:0; right:0; left:0; z-index:200; background:lightgray; border-bottom:solid 1px #AAA; font-size:0.875em; color:#333; text-align:center; }';
  366. $styles += '#content_header table { width:100%; padding:7px 12px 5px; border-collapse:collapse; font-size:0.875rem; }';
  367. $styles += '#content_header td:first-of-type, #content_header td:last-of-type { width:6em; padding:4px 6px 3px; vertical-align:middle; }';
  368. $styles += '#content_header td:first-of-type { float:left; text-align:left; }';
  369. $styles += '#content_header td:last-of-type { float:right; text-align:right; }';
  370. $styles += '#content_header td button { word-break:none; hyphens:none; }';
  371. $styles += '#content_title { padding:4px 1em 3px; vertical-align:middle; word-break:break-word; text-align:center; }';
  372. $styles += '#content_pane[class*="content"] #content_header { display:block !important; }';
  373.  
  374. // Font size button
  375. $styles += '#font_size { background:rgba(128,128,128,0.3); position:absolute; right:1rem; opacity:0; transition:opacity 1s ease-in-out; display:block; z-index:10; }';
  376. $styles += '#font_size span { width:2rem; height:2rem; font-size:2rem; display:block; text-align:center; cursor:pointer; }';
  377. $styles += '#font_size span:first-of-type { opacity:0.3; background:'+ $plus_sign +' center no-repeat; }';
  378. $styles += '#font_size span:last-of-type { opacity:0.3; background:'+ $minus_sign +' center no-repeat; }';
  379. $styles += '#font_size span:hover { opacity:0.5; filter:invert(100%); background-color:#666; }';
  380. $styles += '#content_pane.has_font_content:hover #font_size, #content_pane.has_grid_content:hover #font_size { display:block; opacity:1; }';
  381.  
  382. $styles += '#content_mask { height:'+ window.innerHeight + 'px; position:absolute; top:0; right:0; bottom:0; left:0; display:none; z-index:9998; }';
  383.  
  384. $styles += '#content_image {padding:2em; position:absolute; top:0; right:0; bottom:0;left:0; display:none; background:#333; overflow:auto; text-align:center;}';
  385. $styles += '#content_image img {width:auto; height:auto; max-width:100%; max-height:100%; max-height:calc(100% - 3px); cursor:zoom-in; -webkit-user-select:none; position:relative; top:50%; transform:translateY(-50%);}';
  386. $styles += '#content_image img.zoom_img { max-width:none; max-height:none; cursor:zoom-out; top:0; transform:translateY(0); }';
  387.  
  388. $styles += '#content_embed, #content_iframe { width:100%; height:100%; padding:0; position:absolute; top:0; right:0; bottom:0; left:0; border:0; display:none; }';
  389.  
  390. $styles += '#content_grid { width:auto; padding:0; display:none; position:absolute; right:0; bottom:0; left:0; overflow:auto; font-size:1em; background:#333; grid-gap:0; grid-template-columns:repeat(auto-fit, minmax(150px, 1fr)); grid-template-rows:repeat(auto, 150px); z-index:1; }';
  391. $styles += '#content_grid .image_grid_item { display:inline-block; width:150px; height:150px; float:left; text-align:center; vertical-align:middle; }';
  392. $styles += '#content_grid .image_grid_item.selected { background:#666; }';
  393. $styles += '#content_grid .image_grid_item:hover, #content_grid div.image_grid_item.hovered { background:#555 !important; }';
  394. $styles += '#content_grid .font_grid_item { width:calc(100% - 2rem); padding:1rem 0.75rem; display:block; font-size:3em; text-align:left; outline:none; clear:both; }';
  395. $styles += '#content_grid .font_grid_item:hover, #content_grid div.font_grid_item.hovered { background:#EEE !important; }';
  396. $styles += '#content_grid .font_grid_item.selected { background:#DDD; }';
  397. $styles += '#content_grid div img { width:auto; height:auto; max-width:128px; max-height:128px; position:relative; top:50%; transform:translateY(-50%); opacity:0.8; } ';
  398. $styles += '#content_grid.has_image_grid { display:grid !important; }';
  399. $styles += '#content_grid.has_font_grid, #content_grid.has_grid { background:#FFF; display:block !important; }';
  400. $styles += '#content_grid.has_grid div.selected { background:#DDD; }';
  401. $styles += '#content_grid.has_grid div:hover, #content_grid.has_grid div.hovered { background:#EEE !important; }';
  402.  
  403. $styles += '#content_font { padding:1em; display:none; position:absolute; right:0; bottom:0; left:0; overflow:auto; font-size:1em; word-break:break-all; overflow-wrap:break-word; hyphens:none; outline:none; }';
  404. $styles += '.specimen, .lorem { margin-bottom:1em; white-space:normal; text-align:left; }';
  405. $styles += '.lorem { text-align:justify; word-break:normal; overflow-wrap:normal; hyphens:auto; }';
  406. $styles += '.specimen + .lorem:first-line { letter-spacing:1pt; font-variant:small-caps; }';
  407. $styles += '.lorem + .lorem { columns:2; column-gap:1em;}';
  408. $styles += '.lorem + .lorem + .lorem { margin-bottom:2em; columns:3; }';
  409.  
  410. $styles += '#prev_btn, #next_btn { padding:0 1em; display:none; position:absolute; top:0; bottom:0; z-index:100; opacity:0.6; filter:invert(50%); background: ' + $svg_arrow + ' no-repeat center; }';
  411. $styles += '#prev_btn { left:0 !important; }';
  412. $styles += '#next_btn { right:0; transform:rotate(180deg); }';
  413.  
  414. $styles += '#content_pane.has_image_content #prev_btn, #content_pane.has_image_content #next_btn { display:block !important; }';
  415. $styles += '#content_pane.has_font_content #content_font { display:block; }';
  416. $styles += '#content_pane[class*="hidden"] #content_grid { display:none !important; z-index:auto; }';
  417. $styles += '#content_pane.has_image_content #content_image { display:block !important; }';
  418. $styles += '#content_pane.has_file_content #content_iframe { display:block !important; }';
  419. $styles += '#content_pane.has_pdf_content #content_embed { display:block !important; }';
  420.  
  421. $styles += 'body.dark_mode #sidebar, body.dark_mode #content_header { background:#555; }';
  422. $styles += 'body.dark_mode #sidebar ul.menu { background:#444; box-shadow-color:#111; }';
  423. $styles += 'body.dark_mode #sidebar ul.menu li:hover { background:#666; }';
  424. $styles += 'body.dark_mode #sidebar { border-right-color:#111; }';
  425. $styles += 'body.dark_mode #sidebar_header thead tr, body.dark_mode #sidebar_header tbody tr:first-of-type { border-bottom:solid 1px black; background-color:#444; }';
  426. $styles += 'body.dark_mode #sidebar_header tbody tr:first-of-type td:nth-of-type(even) { border-left-color:#111; border-right-color:#111; }';
  427. $styles += 'body.dark_mode #sidebar_header .menu { border-top-color:#111; }';
  428. $styles += 'body.dark_mode #sidebar_header .menu, body.dark_mode #content_header { border-bottom-color:#111; }';
  429. $styles += 'body.dark_mode #sidebar tr *, body.dark_mode #sidebar li, body.dark_mode #content_header tr { color:#EEE !important; }';
  430. $styles += 'body.dark_mode #details_btn span { color:#333 !important; }';
  431. $styles += 'body.dark_mode #grid_btn, body.dark_mode #parent_dir_menu, body.dark_mode #shortcuts_menu { filter:invert(100%); }';
  432. $styles += 'body.dark_mode #dir_table tr.selected { background:slategray !important; }';
  433. $styles += 'body.dark_mode #dir_table tr:hover { background:#777 !important; }';
  434. $styles += 'body.dark_mode #content_pane { background:#333; }';
  435. $styles += 'body.dark_mode #content_iframe[scr*=".htm"] { filter:invert(87.5%); }';
  436. $styles += 'body.dark_mode #content_pane.has_font_content #content_font { color:#CCC; }';
  437.  
  438. $styles += '#main_content { width:100%; height:100%; border:0; border-collapse:collapse; overflow:hidden; }';
  439.  
  440. $custom_styles.append($styles);
  441. document.head.appendChild($custom_styles);
  442.  
  443. // Conditional Styles:
  444. var $gecko_styles = document.createElement("style");
  445. var $custom_gecko_styles = '';
  446. $custom_gecko_styles += '<style type="text/css">html, body { border: solid 1px gray !important; } button { padding:0; } thead {font-size:100%;} #dir_table .dir::before {position:absolute;} </style>';
  447. $gecko_styles.append($custom_gecko_styles);
  448.  
  449. // for scrollIntoView
  450. var $block = '';
  451.  
  452. if( $userAgent.indexOf('Firefox') > -1 ){
  453. document.head.appendChild($gecko_styles);
  454. $block = 'start';
  455. } else {
  456. $block = 'nearest';
  457. }
  458. // if( $userAgent.indexOf('Chrome') > -1 ){
  459. // Do something
  460. // }
  461.  
  462. // Sidebar Header: Hide invisibles checkbox user setting
  463. if ( $settings.hide_invisibles === true ) {
  464. $inv_checkbox.find('input').prop('checked',true);
  465. $dir_table.addClass('hide_invisibles');
  466. }
  467. // Sidebar Header: Toggle Invisibles checkbox
  468. $inv_checkbox.on('click','input', function(e){
  469. $dir_table.toggleClass('hide_invisibles');
  470. $('.selected').removeClass('selected');
  471. });
  472. // Hide Ignored Files
  473. if ( $settings.hide_ignored_files === true ) {
  474. $dir_table.addClass('hide_ignored');
  475. }
  476. if ( $settings.dark_mode === true ) {
  477. $body.addClass('dark_mode');
  478. }
  479. // Hide hide invisibles chceckbox
  480. if ( platformIsWin() || window.location.href.indexOf('file:') < 0 ) {
  481. $inv_checkbox.hide();
  482. }
  483.  
  484. // ***** END STYLES ***** //
  485.  
  486. // ***** BUILD MENUS ***** //
  487.  
  488. // MENUS: Parents Link Menu Items
  489.  
  490. var parentLinksArr = function() {
  491. var $paths_arr = [];
  492. for ( i = 1, n = $location_arr.length; i < n - 1; i+=1 ) {
  493. $paths_arr[0] = ''; // root
  494. $paths_arr[i] = $paths_arr[i - 1] + $location_arr[i] + '/';
  495. }
  496. return $paths_arr;
  497. };
  498.  
  499. // MENUS: function to build menu list items
  500. var menuItems = function(x,y,i) { // (link, name, count)
  501. var $menu_item = '<li><a href="file:///' + x[i] + '">' + y[i] + '</a></li>';
  502. return $menu_item;
  503. };
  504. // MENUS: Parents Directory Menu Items
  505. var parents_dir_menu_arr = function() {
  506. var $parents_dir_menu_items = [];
  507. for ( var i = 1, n = parentLinksArr().length; i < n; i+=1 ) {
  508. $parents_dir_menu_items[0] = menuItems('/','/',0); // root
  509. $parents_dir_menu_items[i] = menuItems( parentLinksArr(), parentLinksArr(), i);
  510. }
  511. $parents_dir_menu_items.pop(); // remove current directory
  512. $parents_dir_menu_items = $parents_dir_menu_items.reverse().join('').replace(/%20/g,' ');
  513. return $parents_dir_menu_items;
  514. };
  515. $parents_dir_menu.siblings('ul').append( parents_dir_menu_arr() );
  516.  
  517. // MENUS: Root Shortcuts Menu Items
  518. $settings.root_shortcuts = $settings.root_shortcuts.map(i => i + '/'); // append '/' to directory name
  519.  
  520. var root_shortcuts_menu_arr = function() {
  521. if ( $settings.root_shortcuts.length ) {
  522. var $root_shortcut_items = [];
  523. for ( i = 0, n = $settings.root_shortcuts.length; i < n; i+=1 ) {
  524. $root_shortcut_items[i] = menuItems($settings.root_shortcuts,$settings.root_shortcuts,i);
  525. }
  526. $root_shortcut_items = $root_shortcut_items.join('');
  527. return $root_shortcut_items;
  528. }
  529. };
  530.  
  531. // MENUS: User Shortcuts Menu Items
  532. var $user_shortcuts_display_name = $settings.user_shortcuts.map(i => $settings.user_name + '/' + i + '/' ); // build display names
  533. $settings.user_shortcuts = $settings.user_shortcuts.map(i => 'users/' + $settings.user_name + '/' + i + '/'); // build link fragments
  534.  
  535. var userShortcutsMenuArr = function() {
  536. if ( $settings.user_name && $settings.user_shortcuts.length ) {
  537. var $user_shortcut_items = [];
  538. for ( i = 0, n = $settings.user_shortcuts.length; i < n; i+=1 ) {
  539. $user_shortcut_items[i] = menuItems($settings.user_shortcuts,$user_shortcuts_display_name,i);
  540. }
  541. $user_shortcut_items = $user_shortcut_items.join('');
  542. return $user_shortcut_items;
  543. }
  544. };
  545.  
  546. // MENUS: File Shortcuts Menu Items
  547. var $file_shortcuts_display_name = $settings.file_shortcuts.map(i => i.split('/').pop()); // get file names from paths
  548.  
  549. var fileShortcutsMenuArr = function() {
  550. if ( $settings.file_shortcuts.length ) {
  551. var $file_shortcut_items = [];
  552. for ( i = 0, n = $settings.file_shortcuts.length; i < n; i+=1 ) {
  553. $file_shortcut_items[i] = menuItems($settings.file_shortcuts,$file_shortcuts_display_name,i);
  554. }
  555. $file_shortcut_items = $file_shortcut_items.join('').replace(/\/<\/a>/g,'<\/a>').replace(/<a\s/g,'<a class="file_shortcut" ').replace(/%20/g,' ');
  556. return $file_shortcut_items;
  557. }
  558. };
  559. $shortcuts_menu.siblings('ul').append( root_shortcuts_menu_arr(), $divider, userShortcutsMenuArr(), $divider.clone(), fileShortcutsMenuArr(), $divider.clone() );
  560.  
  561. // MENUS: Show Menu on click
  562. function showMenus(el) {
  563. var $position = $(el).position();
  564. $(el).find('ul').css({'top':$position.top + $(el).innerHeight() + 'px'}).toggle().parent('td').siblings('td').find('.menu').hide();
  565. }
  566. $parents_dir_menu.add($shortcuts_menu).parent('td').on('click',function(e) {
  567. e.stopPropagation();
  568. showMenus(this);
  569. });
  570.  
  571. // ***** END BUILD MENUS ***** //
  572.  
  573. // ***** END BUILD UI ***** //
  574.  
  575. // ***** SIDEBAR ***** //
  576.  
  577. // DIRECTORY TABLE
  578.  
  579. // DIRECTORY TABLE VARIABLES
  580. if ( $dir_table.hasClass('table') ) {
  581.  
  582. $dir_table_head = $dir_table.find('> thead').length ? $dir_table.find('> thead') : $dir_table.addClass('headless').find('> tbody > tr:first-of-type') ;
  583. $dir_table_head.attr('id','thead');
  584. $dir_table_head_cell = $dir_table_head.find('th');
  585. $dir_table_head_name = $dir_table_head.find('th:contains("Name")');
  586. $dir_table_head_name.addClass('name');
  587. $dir_table_head_details = $dir_table_head_name.nextAll();
  588. $dir_table_head_details.addClass('details');
  589.  
  590. $dir_table_body = $dir_table.find('> tbody');
  591. $dir_table_body.attr('id','tbody');
  592. $dir_table_rule = $dir_table_body.find('hr').closest('tr');
  593. $dir_table_rule.addClass('rule');
  594. $dir_table_row = $dir_table_body.find('> tr').not('#thead').not('.rule');
  595. $dir_table_cell = $dir_table_row.find('td');
  596. $dir_table_link = $dir_table_cell.find('a');
  597. $dir_table_item_name = $dir_table_link.parent('td');
  598. $dir_table_item_name.addClass('name');
  599. $dir_table_item_icon = $dir_table_item_name.add($dir_table_head_name).prev();
  600. $dir_table_item_icon.addClass('icon'); // for directory lists with separate td for icons
  601. $dir_table_details = $dir_table_item_name.nextAll();
  602. $dir_table_details.addClass('details');
  603. }
  604. if( $userAgent.indexOf('Firefox') > -1 ) {
  605. $dir_table.addClass('firefox');
  606. }
  607. if ( $dir_table.hasClass('list') ) { // Apache server
  608. $dir_table_wrapper.addClass('headless');
  609. $dir_table_head = '';
  610. $dir_table_head_cell = '';
  611. $dir_table_head_name = '';
  612. $dir_table_head_details = '';
  613. $dir_table_body = '';
  614. $dir_table_row = $dir_table.find('li');
  615. $dir_table_cell = '';
  616. $dir_table_details = '';
  617. $dir_table_link = $dir_table_row.find('a');
  618. // $dir_table_link.addClass('name');
  619. $dir_table_item_name = $dir_table_link.text();
  620. $sidebar.append($dir_table_wrapper);
  621. }
  622. $dir_table.detach().attr('id','dir_table');
  623.  
  624. // ***** DIR_TABLE SETUP ***** //
  625.  
  626. // Sidebar Header: Show details button click function
  627. function detailsButton() {
  628. $dir_table.toggleClass('show_details');
  629. $dir_table_body.css({'top':$dir_table_head.height() + 1 +'px'});
  630. $details_btn.find('span').toggle();
  631. }
  632. $details_btn.on('click', detailsButton );
  633.  
  634. // Dir_table: Row hover effects
  635. $dir_table_row.hover(function() {
  636. // Highlight corresponding grid item
  637. if ( $content_grid.is(':visible') ) {
  638. $this_link = $(this).find('a').attr('href');
  639. $content_grid.find('[href="' + $this_link + '"]').closest('div').addClass('hovered');
  640. }
  641. }, function() {
  642. if ( $content_grid.is(':visible') ) {
  643. $content_grid.find('.hovered').removeClass('hovered');
  644. }
  645. });
  646.  
  647. // Dir_table: create link arrays
  648. var $dir_table_dir_link_arr = [];
  649. var $dir_table_file_link_arr = [];
  650. var $dir_table_file_ext_arr = [];
  651. $dir_table_row.not('.ignore,.invisible').find('a').each(function() {
  652. $this_link = $(this).attr('href').toLowerCase();
  653. if ( $this_link.endsWith('/') ) {
  654. $dir_table_dir_link_arr.push($this_link);
  655. return $dir_table_dir_link_arr;
  656. } else {
  657. var $this_link_ext = $this_link.slice($this_link.lastIndexOf('.'));
  658. $dir_table_file_link_arr.push($this_link);
  659. if ( $dir_table_file_ext_arr.indexOf($this_link_ext) < 0 ) {
  660. $dir_table_file_ext_arr.push($this_link_ext);
  661. }
  662. return $dir_table_file_link_arr, $dir_table_file_ext_arr;
  663. }
  664. });
  665. // Dir_table: array of all dir_table links
  666. var $dir_table_link_arr = [];
  667. $dir_table_link_arr = $dir_table_dir_link_arr.concat($dir_table_file_link_arr);
  668.  
  669. // Dir_table: array of supported image types
  670. var $image_ext_arr = ['.jpg','.jpeg','.png','apng','.gif','.bmp','webp'];
  671. var $font_ext_arr = ['.otf','.ttf','.woff','.woff2'];
  672. var $font_family_arr = [];
  673.  
  674. // Dir_table: Classify items
  675. $dir_table_row.each(function() {
  676.  
  677. $this_link = $(this).find('a').attr('href');
  678.  
  679. if ( $this_link != undefined ) {
  680.  
  681. $this_link = $this_link.toString().toLowerCase();
  682.  
  683. // Directories or files
  684. if ( $this_link.endsWith('/') ) {
  685. $(this).addClass('dir');
  686. } else {
  687. $(this).addClass('file');
  688. }
  689. // pdf
  690. if ( $this_link.endsWith('.pdf') ) {
  691. $(this).addClass('pdf');
  692. } else if ( $.inArray( $this_link.slice($this_link.lastIndexOf('.') ), $image_ext_arr ) != -1 ) {
  693. $(this).addClass('img');
  694. } else if ( $.inArray( $this_link.slice($this_link.lastIndexOf('.') ), $font_ext_arr ) != -1 ) {
  695. $(this).addClass('font');
  696. }
  697. // invisibles
  698. if ( $this_link.slice($this_link.lastIndexOf('/') + 1 ) === '.' || $this_link.startsWith('.') || $(this).find('a').text().startsWith('.') ) {
  699. $(this).addClass('invisible');
  700. }
  701. // ignored
  702. if ( $settings.ignore_files === true ) {
  703. for ( i = 0, n = $settings.ignore_file_types.length; i < n; i+=1 ) {
  704. if ( $this_link.endsWith( $settings.ignore_file_types[i] ) ) {
  705. $(this).closest('#dir_table > tbody > tr').addClass('ignore');
  706. }
  707. }
  708. }
  709. // directories as Files and hide ignored files
  710. if ( $settings.apps_as_dirs === false ) {
  711. if ( $this_link.endsWith('.app/') ) {
  712. $(this).addClass('ignore app');
  713. var $app_name = $(this).find('a').text().slice(0,-1);
  714. $(this).find('a').text($app_name);
  715. }
  716. }
  717. }
  718. }); // end classify dir_table items
  719.  
  720. if ( $dir_table.hasClass('table') ) {
  721. $dir_table.appendTo($sidebar);
  722. } else {
  723. $dir_table.appendTo($dir_table_wrapper);
  724. }
  725.  
  726. // Show grid button if images or fonts are found
  727. if ( $dir_table.find('.img').length ) {
  728. $dir_table.add($grid_btn).addClass('has_images');
  729. }
  730. if ( $dir_table.find('.font').length ) {
  731. $dir_table.add($grid_btn).addClass('has_fonts');
  732. }
  733.  
  734. // ***** End dir_table setup ***** //
  735.  
  736. // ***** APPEND MAIN CONTENT ***** //
  737.  
  738. var $main_content = $('<table id="main_content"><tbody><tr></tr></tbody></table>');
  739. $main_content.find('tr').append( $sidebar_wrapper, $content_pane );
  740.  
  741. $body.prepend($main_content);
  742.  
  743. // ***************************** //
  744.  
  745. // ***** SHOW/HIDE CONTENT ***** //
  746.  
  747. // MENUS: Hide Menu function
  748. function hideMenu() {
  749. $('.menu').hide();
  750. }
  751. $(document).on('click', hideMenu );
  752.  
  753. // Set content height
  754. function setContentHeight() {
  755. var $dir_table_head_height = $dir_table_head.length ? $dir_table_head.height() : 0;
  756. var $content_headerHeight = $content_header.outerHeight();
  757. $dir_table.add($dir_table_wrapper).css({'height':window.innerHeight - $sidebar_header.outerHeight() });
  758. $dir_table.find($dir_table_body).css({'top': $dir_table_head_height });
  759. $content_image.css({'top':$content_headerHeight });
  760. $content_grid.add($content_embed).add($content_iframe).add($content_font).css({'height':window.innerHeight - $content_headerHeight,'top':$content_headerHeight });
  761. $content_font_size.css({'top':$content_headerHeight + 13 });
  762. }
  763. setContentHeight();
  764.  
  765. $('window').on('resize', setContentHeight );
  766.  
  767. function setContentTitle() {
  768. if ( $content_pane.hasClass('has_grid_content') && $content_grid.hasClass('has_grid') ) {
  769. $content_title.empty().prepend('Images and Fonts from: ' + $current_dir_name);
  770. } else if ( $content_pane.hasClass('has_grid_content') && $content_grid.hasClass('has_image_grid') ) {
  771. $content_title.empty().prepend('Images from: ' + $current_dir_name);
  772. } else if ( $content_pane.hasClass('has_grid_content') && $content_grid.hasClass('has_font_grid') ) {
  773. $content_title.empty().prepend('Fonts from: ' + $current_dir_name);
  774. } else {
  775. $content_title.empty().prepend( $('.selected').find('a').text() );
  776. }
  777. if ( $('.selected').hasClass('ignore') ) {
  778. $content_title.append(' (Ignored content)' );
  779. }
  780. }
  781.  
  782. // Get image dimensions
  783. function getDimensions(link, callback) {
  784. var img = new Image();
  785. img.src = link;
  786. img.onload = function() { callback( this.width, this.height ); };
  787. }
  788.  
  789. function scrollSidebar(row) {
  790. row[0].scrollIntoView({ behavior:'smooth', block:$block, inline:'nearest' });
  791. }
  792. function scrollGrid(item) {
  793. item[0].scrollIntoView({ behavior:'smooth', block:$block, inline:'nearest' });
  794. }
  795.  
  796. // Select row on click and set classes for $content_pane
  797. function selectThis(row) {
  798. row.addClass('selected').siblings().removeClass('selected');
  799. $selected = $dir_table.find('.selected');
  800. scrollSidebar($selected);
  801. if ( row.hasClass('dir') ) {
  802. closeThis(); // empty content pane
  803. setContentTitle();
  804. $content_pane.removeClass().addClass('has_dir_content');
  805. }
  806. var $grid_selected = $content_grid.find('div.font_grid_item[href="'+ row.find('a').attr('href') +'"]').add('div a[href="'+ row.find('a').attr('href') +'"]').parent('div').addBack();
  807. if ( $content_pane.hasClass('has_grid_content') ) {
  808. $grid_selected.addClass('selected').siblings().removeClass('selected');
  809. $grid_selected = $content_grid.find('.selected');
  810. // scrollGrid($grid_selected); // grid scroll is not working reliably
  811. }
  812. }
  813.  
  814. function showIgnored() {
  815. closeThis();
  816. $content_pane.addClass('has_ignored_content');
  817. $content_title.append(' (Ignored content)' );
  818. }
  819.  
  820. function showImage(row,link) {
  821. $content_pane.addClass('has_image_content');
  822. $content_image.find('img').removeClass('zoom_img').attr('src',link);
  823. getDimensions( link, function( width, height ) {
  824. $content_title.append(' <span style="text-transform:lowercase;">(' + width + 'px &times; ' + height + 'px</span>)' );
  825. });
  826. $content_grid.find('a[href="' + row.find('a').attr('href') + '"]').parent('div').addClass('selected').siblings().removeClass('selected');
  827. }
  828.  
  829. function showPdf(link) {
  830. $content_pane.addClass('has_pdf_content');
  831. $content_embed.attr('type','application/pdf').attr('src',link + '?#zoom=100&scrollbar=1&toolbar=1&navpanes=1');
  832. }
  833.  
  834. function showFile(link) {
  835. $content_pane.addClass('has_file_content');
  836. $content_iframe.attr('src',link);
  837. }
  838.  
  839. function showFont(row,link) {
  840. var $font_family = row.find('.name').text();
  841.  
  842. addCustomStyle($font_family,link);
  843.  
  844. $content_pane.addClass('has_font_content');
  845. $content_font.css({ 'font-family':'"'+ $font_family +'"' });
  846. }
  847.  
  848. function addCustomStyle(font_family,link) {
  849. if ( $font_family_arr.indexOf(font_family) == -1 ) {
  850. $font_family_arr.push(font_family);
  851. $custom_font_styles.append('@font-face { font-family: "'+ font_family +'"; src: url("'+ link +'"); }'); // only add style if it doesn't exist
  852. }
  853. }
  854.  
  855. // Show selected content
  856. function showThis(row,link) {
  857.  
  858. if ( $content_pane.hasClass('has_grid_content') ) {
  859. $content_pane.removeClass('has_grid_content').addClass('has_hidden_grid'); // hide grid when showing new content
  860. } else
  861. if ( $content_pane.hasClass('has_hidden_grid') ) {
  862. $content_pane.removeClass().addClass('has_hidden_grid'); // keep grid hidden when showing new content
  863. } else {
  864. $content_pane.removeClass();
  865. }
  866.  
  867. if ( row.hasClass('ignore') ) {
  868. showIgnored();
  869. return;
  870. }
  871. if ( row.hasClass('img') ) {
  872. showImage(row,link);
  873. return;
  874. }
  875. if ( row.hasClass('pdf') ) {
  876. showPdf(link);
  877. return;
  878. }
  879. if ( row.hasClass('font') ) {
  880. showFont(row,link);
  881. return;
  882. }
  883. if ( row.hasClass('file') ) {
  884. showFile(link);
  885. return;
  886. }
  887. }
  888.  
  889. // ***** MAIN CLICK FUNCTION FOR SHOWING CONTENT ***** //
  890.  
  891. function clickDirTableLink(link) {
  892. var $this_row = link.closest('#dir_table > tbody > tr, #dir_table > li');
  893. $this_link = link.attr('href');
  894.  
  895. if ( $this_row.hasClass('dir') ) {
  896. window.location = $this_link;
  897. }
  898. hideMenu();
  899. showThis($this_row,$this_link);
  900. selectThis($this_row);
  901. setContentTitle();
  902. setContentHeight();
  903. }
  904. $dir_table_row.on('click','a',function(e) {
  905. e.preventDefault();
  906. closeContent();
  907. clickDirTableLink($(this));
  908. });
  909.  
  910. // Auto-select file from file shortcut list;
  911. // Limitations: only loads last file from list found in directory, doesn't know anything about which actual file shortcut was selected
  912. function autoSelectFile() {
  913. if ( $settings.file_shortcuts.length ) {
  914. for ( i = 0, n = $settings.file_shortcuts.length; i < n; i+=1 ) {
  915. if ( $.inArray($settings.file_shortcuts[i], $dir_table_link_arr ) ) {
  916. $dir_table.find( 'a[href*="/' + $settings.file_shortcuts[i] + '"]').click();
  917. }
  918. }
  919. }
  920. }
  921. autoSelectFile();
  922.  
  923. // File shortcuts: load directory then auto-select file
  924. function showFileShortcut(item) {
  925. e.preventDefault();
  926. $this_link = item.attr('href');
  927. var $this_dir = $this_link.slice(0,$this_link.lastIndexOf('/') );
  928. window.location = $this_dir;
  929. }
  930. $('.file_shortcut').on('click',showFileShortcut );
  931.  
  932. // Reload Button
  933. function reloadThis() {
  934. if ( $content_pane.hasClass('has_grid_content') ) {
  935. $grid_btn.click();
  936. } else if ( $content_pane.is('[class*="content"]') ) {
  937. $('.selected').find('a').click();
  938. } else {
  939. return;
  940. }
  941. }
  942. $content_reload_btn.on('click', reloadThis );
  943.  
  944. function closeContent() {
  945. $content_image.find('img').removeAttr('src');
  946. $content_embed.removeAttr('src');
  947. $content_iframe.removeAttr('src');
  948. $content_font.css({'font-family':''});
  949. }
  950.  
  951. function closeThis() {
  952. hideMenu();
  953. if ( $content_pane.hasClass('has_grid_content') ) {
  954. $content_pane.removeClass('has_grid_content');
  955. $content_grid.removeClass().empty().css({'font-size':'1em'});
  956. } else if ( $content_pane.hasClass('has_hidden_grid') ) {
  957. $content_pane.removeClass().addClass('has_grid_content');
  958. closeContent();
  959. } else {
  960. $content_pane.removeClass();
  961. closeContent();
  962. }
  963. setContentTitle();
  964. }
  965. // Close content button
  966. $content_close_btn.on( 'click', closeThis );
  967.  
  968.  
  969. // ***** KEYBOARD EVENTS ***** //
  970. function navigateToThis(el) {
  971. if ( $content_pane.hasClass('has_grid_content') ) {
  972. selectThis(el);
  973. } else {
  974. el.find('a').click();
  975. }
  976. }
  977.  
  978. $body.on('keydown',$dir_table,function(e) {
  979.  
  980. var $selected = $dir_table_row.filter('.selected');
  981. var $selected_href = $selected.find('a').attr('href');
  982. var $first_item = $dir_table_row.filter(':visible').first();
  983. var $last_item = $dir_table_row.filter(':visible').last();
  984. var $prev_item = $selected.prevAll(':visible').first();
  985. var $next_item = $selected.nextAll(':visible').first();
  986. var $first_image = $dir_table_row.filter('.img:visible').first();
  987. var $last_image = $dir_table_row.filter('.img:visible').last();
  988. var $prev_image = $selected.prevAll('.img:visible').first();
  989. var $next_image = $selected.nextAll('.img:visible').first();
  990. var $first_font = $dir_table_row.filter('.font:visible').first();
  991. var $last_font = $dir_table_row.filter('.font:visible').last();
  992. var $prev_font = $selected.prevAll('.font:visible').first();
  993. var $next_font = $selected.nextAll('.font:visible').first();
  994.  
  995. switch ( e.key ) {
  996.  
  997. case 'ArrowUp':
  998.  
  999. // Go to parent folder
  1000. if ( (navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey) ) {
  1001. window.location = $parent_dir_link;
  1002. break;
  1003. }
  1004. // Allow arrow navigation within
  1005. if ( $('*[contentEditable="true"').is(':focus') ) {
  1006. return;
  1007. }
  1008. e.preventDefault();
  1009. if ( $first_item.hasClass('selected') || $selected.length < 1 ) {
  1010. $last_item.hasClass('dir') ? selectThis($last_item) : $last_item.find('a').click();
  1011. } else {
  1012. $prev_item.hasClass('dir') ? selectThis($prev_item) : $prev_item.find('a').click();
  1013. }
  1014. break;
  1015.  
  1016. case 'ArrowDown':
  1017.  
  1018. if ( (e.ctrl || e.metaKey) && $selected.hasClass('app') && $settings.apps_as_dirs === false ) {
  1019. return;
  1020. } else if ( $('*[contentEditable="true"').is(':focus') ) {
  1021. return;
  1022. } else if ( (e.ctrl || e.metaKey) && $selected.hasClass('dir') ) {
  1023. window.location = $selected_href;
  1024. break;
  1025. }
  1026.  
  1027. e.preventDefault();
  1028. if ( $last_item.hasClass('selected') || $selected.length < 1 ) {
  1029. $first_item.hasClass('dir') ? selectThis($first_item) : $first_item.find('a').click();
  1030. } else {
  1031. $next_item.hasClass('dir') ? selectThis($next_item) : $next_item.find('a').click();
  1032. }
  1033. break;
  1034.  
  1035. case 'ArrowLeft':
  1036.  
  1037. if ( (e.ctrl || e.metaKey) || ( e.ctrl && e.metaKey ) ) {
  1038. return;
  1039. } else if ( $('*[contentEditable="true"').is(':focus') ) {
  1040. return;
  1041. }
  1042. // Navigate Grid or Images
  1043. if ( $selected.length < 1 ) {
  1044. $last_image.length ? navigateToThis($last_image) : navigateToThis($last_font);
  1045. } else if ( $first_image.hasClass('selected') || $selected.length < 1 ) {
  1046. $last_font.length ? navigateToThis($last_font) : navigateToThis($last_image);
  1047. } else if ( $first_font.hasClass('selected') || $selected.length < 1 ) {
  1048. $last_image.length ? navigateToThis($last_image) : navigateToThis($last_font);
  1049. } else if ( $selected.hasClass('img') && $prev_image.length ) {
  1050. navigateToThis($prev_image);
  1051. } else {
  1052. navigateToThis($prev_font);
  1053. }
  1054. break;
  1055.  
  1056. case 'ArrowRight':
  1057.  
  1058. if ( (e.ctrl || e.metaKey) || ( e.ctrl && e.metaKey ) ) {
  1059. return;
  1060. } else if ( $('*[contentEditable="true"').is(':focus') || $selected.hasClass('dir ignore') ) {
  1061. return;
  1062. }
  1063. // Navigate Grid or Images
  1064. if ( $selected.hasClass('dir') ) {
  1065. window.location = $selected_href; // Open directory
  1066. }
  1067. if ( $selected.length < 1 ) {
  1068. $first_image.length ? navigateToThis($first_image) : navigateToThis($first_font);
  1069. } else if ( $last_image.hasClass('selected') || $selected.length < 1 ) {
  1070. $first_font.length ? navigateToThis($first_font) : navigateToThis($first_image);
  1071. } else if ( $last_font.hasClass('selected') || $selected.length < 1 ) {
  1072. $first_image.length ? navigateToThis($first_image) : navigateToThis($first_font);
  1073. } else if ( $selected.hasClass('img') && $next_image.length ) {
  1074. navigateToThis($next_image);
  1075. } else {
  1076. navigateToThis($next_font);
  1077. }
  1078. break;
  1079.  
  1080. case 'Enter':
  1081. // Open directories (or ignore)
  1082. if ( $selected.hasClass('app') && $settings.apps_as_dirs === false ) {
  1083. break;
  1084. } else {
  1085. $selected.find('a').click();
  1086. }
  1087. break;
  1088.  
  1089. case 'd':
  1090. // Toggle Invisibles with Command-i
  1091. if ( (navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey) ) {
  1092. e.preventDefault();
  1093. e.stopPropagation();
  1094. $details_btn.click();
  1095. }
  1096. break;
  1097.  
  1098. case 'g':
  1099. // Show image Grid
  1100. if ( (navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey) ) {
  1101. e.preventDefault();
  1102. e.stopPropagation();
  1103. $grid_btn.click();
  1104. }
  1105. break;
  1106.  
  1107. case 'i':
  1108. // Toggle Invisibles with Command-i
  1109. if ( (navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey) ) {
  1110. e.preventDefault();
  1111. e.stopPropagation();
  1112. $inv_checkbox.click();
  1113. }
  1114. break;
  1115.  
  1116. case 'o':
  1117. // Cmd/Ctrl + Shift + O: Open selected item in new window
  1118. if ( (navigator.platform.match("Mac") ? e.metaKey && e.shiftKey : e.ctrlKey && e.shiftKey ) ) {
  1119. window.open($selected_href);
  1120. }
  1121. break;
  1122.  
  1123. case 'r':
  1124. // Cmd/Ctrl + Shift + O: Open selected item in new window
  1125. if ( $content_pane.is('[class*="has_"]') ) {
  1126. e.preventDefault();
  1127. $content_reload_btn.click();
  1128. } else {
  1129. return;
  1130. }
  1131. break;
  1132.  
  1133. case 'w':
  1134. // Close content pane if Close button visible with Command-w
  1135. // Doesn't work in Firefox: can't override default keybinding
  1136. if ( (navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey) && ($content_pane.is('[class*="has_"]')) ) {
  1137. e.preventDefault();
  1138. e.stopPropagation();
  1139. $content_close_btn.click();
  1140. }
  1141. break;
  1142.  
  1143. case '.':
  1144. // Increase font preview size
  1145. if ( (navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey) && e.shiftKey ) {
  1146. $('#increase').click();
  1147. }
  1148. break;
  1149.  
  1150. case ',':
  1151. // Dencrease font preview size
  1152. if ( (navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey) && e.shiftKey ) {
  1153. $('#decrease').click();
  1154. }
  1155. break;
  1156.  
  1157. case 'tab':
  1158. break;
  1159.  
  1160. } // end switch
  1161.  
  1162. });
  1163.  
  1164. // ***** END KEYBOARD EVENTS ***** //
  1165.  
  1166. // ***** IMAGE NAVIGATION ***** //
  1167.  
  1168. $prev_btn.on( 'click', function(event) {
  1169. e = $.Event("keydown");
  1170. e.key = 'ArrowLeft';
  1171. $dir_table.trigger(e);
  1172. });
  1173.  
  1174. $next_btn.on( 'click', function(event) {
  1175. e = $.Event("keydown");
  1176. e.key = 'ArrowRight';
  1177. $dir_table.trigger(e);
  1178. });
  1179.  
  1180. // Zoom Images
  1181. $content_image.find('img').on('click',function() {
  1182. $(this).toggleClass('zoom_img');
  1183. });
  1184.  
  1185. // ***** GRIDS ***** //
  1186.  
  1187. var $this_ext;
  1188. var $font_family;
  1189.  
  1190. var imageGridItems = function() {
  1191. var $image_grid_items_arr = [];
  1192. $dir_table_row.filter('.img').each(function() {
  1193.  
  1194. $this_link = $(this).find('a').attr('href');
  1195. $this_ext = $this_link.toLowerCase().slice($this_link.lastIndexOf('.'));
  1196.  
  1197. if ( $.inArray( $this_ext, $image_ext_arr ) != -1 ) { // if this row file ext is in the image extension array
  1198. $image_grid_item_el.find('a').attr('href',$this_link).find('img').attr('src',$this_link);
  1199. $image_grid_items_arr.push( $image_grid_item_el.clone() );
  1200. }
  1201. });
  1202. return $image_grid_items_arr;
  1203. };
  1204.  
  1205. var fontGridItems = function() {
  1206. var $font_grid_items_arr = [];
  1207. $dir_table_row.filter('.font').each(function() {
  1208.  
  1209. $this_link = $(this).find('a').attr('href');
  1210. $font_family = $(this).find('.name').text();
  1211.  
  1212. addCustomStyle( $font_family, $this_link );
  1213.  
  1214. $font_grid_item_el.attr('href',$this_link).css({ 'font-family':'"'+ $font_family +'"' }).empty().append( $font_family.slice( 0,$font_family.lastIndexOf('.') ) );
  1215. $font_grid_items_arr.push($font_grid_item_el.clone());
  1216. });
  1217. return $font_grid_items_arr;
  1218. };
  1219.  
  1220. // Grid Button Click
  1221. function showGrid() {
  1222. $content_pane.removeClass('has_hidden_grid').addClass('has_grid_content');
  1223.  
  1224. if ( $dir_table.hasClass('has_images') && ( $dir_table.hasClass('has_fonts') ) ) {
  1225. $content_grid.empty().append( imageGridItems() ).append( fontGridItems() );
  1226. $content_grid.removeClass().addClass('has_grid');
  1227. } else if ( $dir_table.hasClass('has_images') ) {
  1228. $content_grid.empty().append( imageGridItems() );
  1229. $content_grid.removeClass().addClass('has_image_grid');
  1230. } else {
  1231. $content_grid.empty().append( fontGridItems() );
  1232. $content_grid.removeClass().addClass('has_font_grid');
  1233. }
  1234. setContentTitle();
  1235. setContentHeight();
  1236. }
  1237. $grid_btn.on('click', showGrid );
  1238.  
  1239. $('#show_image_grid').on('click',function(e) {
  1240. e.stopPropagation();
  1241. $content_pane.removeClass('has_hidden_grid').addClass('has_grid_content');
  1242. $content_grid.empty().append( imageGridItems() );
  1243. $content_grid.removeClass().addClass('has_image_grid');
  1244. setContentTitle();
  1245. setContentHeight();
  1246. });
  1247.  
  1248. $('#show_font_grid').on('click',function(e) {
  1249. e.stopPropagation();
  1250. $content_pane.removeClass('has_hidden_grid').addClass('has_grid_content');
  1251. $content_grid.empty().append( fontGridItems() );
  1252. $content_grid.removeClass().addClass('has_font_grid');
  1253. setContentTitle();
  1254. setContentHeight();
  1255. });
  1256.  
  1257. // GRID ITEMS
  1258. var thisGridItemLink = function(el) {
  1259. $this_link = el.find('a').attr('href') ? el.find('a').attr('href') : el.attr('href');
  1260. return $this_link;
  1261. };
  1262.  
  1263. // Grid Item Hover
  1264. $content_grid.on('mouseenter','> div:not(".selected")',function() {
  1265. $dir_table.find('a[href="' + thisGridItemLink($(this)) + '"]').addClass('hovered');
  1266. }).on('mouseleave','> div:not(".selected")',function() {
  1267. $dir_table.find('a[href="' + thisGridItemLink($(this)) + '"]').removeClass('hovered');
  1268. });
  1269.  
  1270. // Grid Item Click
  1271. $content_grid.on('click','> div[class*="item"]',function(e) {
  1272. e.preventDefault();
  1273. $dir_table.find('a[href="' + thisGridItemLink($(this)) + '"]').click();
  1274. });
  1275.  
  1276. // ***** FONT PREVIEWS ***** //
  1277.  
  1278. var $em = parseFloat(getComputedStyle(document.body).fontSize); // pts/em
  1279.  
  1280. $('#font_size').on('click','span',function() {
  1281.  
  1282. if ( $(this).attr('id') === 'increase' ) {
  1283. if ( $content_pane.is('.has_grid_content.has_font_content') ) {
  1284. $content_grid.css({'font-size':(parseFloat($content_grid.css('font-size'))/$em * 1.125) +'em'});
  1285. return;
  1286. }
  1287.  
  1288. if ( $content_pane.is('.has_hidden_grid.has_font_content') ) {
  1289. $content_font.css({'font-size':(parseFloat($content_font.css('font-size'))/$em * 1.125) +'em'});
  1290. return;
  1291. }
  1292. if ( $('#content_pane.has_font_content').length ) {
  1293. $content_font.css({'font-size':(parseFloat($content_font.css('font-size'))/$em * 1.125) +'em'});
  1294. return;
  1295. }
  1296. }
  1297.  
  1298. if ( $(this).attr('id') === 'decrease' ) {
  1299. if ( $content_pane.is('.has_grid_content.has_font_content') ) {
  1300. $content_grid.css({'font-size':(parseFloat($content_grid.css('font-size'))/$em * 8)/9 +'em'});
  1301. return;
  1302. }
  1303. if ( $content_pane.is('.has_hidden_grid.has_font_content') ) {
  1304. $content_font.css({'font-size':(parseFloat($content_font.css('font-size'))/$em * 8)/9 +'em'});
  1305. return;
  1306. }
  1307. if ( $('#content_pane.has_font_content #content_font').length ) {
  1308. $content_font.css({'font-size':(parseFloat($content_font.css('font-size'))/$em * 8)/9 +'em'});
  1309. return;
  1310. }
  1311. }
  1312. });
  1313. // if ( $(this).attr('id') == 'decrease' ) {
  1314. // $('#content_pane:not(.has_grid_content) #$content_font').add('#content_pane:not(.has_hidden_grid) #content_grid.has_font_grid').css({'font-size':(parseFloat($content_font.css('font-size'))/$em * 8)/9 +'em'});
  1315. // }
  1316.  
  1317. // ***** END FONT PREVIEWS ***** //
  1318.  
  1319. // Resize Sidebar/Content Pane
  1320. $handle.on('mousedown',function(f) {
  1321. f.stopPropagation();
  1322. var $startX = f.pageX;
  1323. var $sidebar_width = $sidebar_wrapper.width();
  1324. var $window_width = window.innerWidth;
  1325. $content_mask.show(); // needed to prevent interactions with iframe
  1326. $sidebar_wrapper.css({'-webkit-user-select':'none','-moz-user-select':'none','user-select':'none'});
  1327.  
  1328. $(document).on('mousemove',function(e) {
  1329. e.stopPropagation();
  1330. var $deltaX = e.pageX - $startX;
  1331. if ( e.pageX > 200 && e.pageX < $window_width - 200 ) {
  1332. $sidebar_wrapper.css({'width':$sidebar_width + $deltaX + 'px'});
  1333. $content_pane.css({'width':($window_width - $sidebar_width) - $deltaX + 'px'});
  1334. }
  1335. setContentHeight();
  1336. });
  1337. $(document).on('mouseup',function() {
  1338. $content_mask.hide();
  1339. $sidebar_wrapper.css({'-webkit-user-select':'auto','-moz-user-select':'auto','user-select':'auto'});
  1340. $(document).off('mousemove');
  1341. });
  1342. });
  1343.  
  1344. })();