file_selector.html 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. <html>
  2. <head>
  3. <title locale="title">File Selector</title>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0 user-scalable=no">
  6. <link rel="stylesheet" href="../../script/tocas/tocas.css">
  7. <link rel="stylesheet" href="../../script/ao.css">
  8. <script type="text/javascript" src="../../script/tocas/tocas.js"></script>
  9. <script type="text/javascript" src="../../script/jquery.min.js"></script>
  10. <script type="text/javascript" src="../../script/ao_module.js"></script>
  11. <script type="text/javascript" src="../../script/applocale.js"></script>
  12. <style>
  13. body{
  14. background-color:white;
  15. }
  16. .navi{
  17. padding:8px;
  18. background-color:#fcfcfc;
  19. border-bottom:2px solid #34b7eb;
  20. position:fixed;
  21. left:0px;
  22. top:0px;
  23. width:100%;
  24. z-index:99;
  25. }
  26. .pusher{
  27. margin-top:46px;
  28. margin-left:200px;
  29. width: calc(100% - 200px);
  30. }
  31. .pusher .fileListWrapper{
  32. padding-left:20px;
  33. padding-right:20px;
  34. }
  35. .navi .button{
  36. box-shadow: 0 1px 1px 0px rgb(190, 190, 190) !important;
  37. }
  38. .list .item{
  39. cursor:pointer;
  40. }
  41. .list .item:hover{
  42. color:#c7c7c7 !important;
  43. }
  44. .extrapadding{
  45. padding-left:6px !important;
  46. padding-right:6px !important;
  47. }
  48. .fileObject{
  49. overflow-wrap: break-word !important;
  50. display: block !important;
  51. padding:12px !important;
  52. font-size:98%;
  53. }
  54. .fileObject .fileInfo{
  55. display:inline-block !important;
  56. word-break: break-all;
  57. text-overflow: ellipsis !important;
  58. overflow: hidden;
  59. color:black;
  60. user-select: none;
  61. }
  62. .fileObject.selected{
  63. background-color:#d2f2f7 !important;
  64. }
  65. .fileObject.item:hover{
  66. background-color:#f2f2f2;
  67. }
  68. </style>
  69. </head>
  70. <body>
  71. <div class="navi">
  72. <button id="sidebarToggleBtn" class="ts icon tiny button" onclick="ts('.sidebar').sidebar('toggle');"><i class="content icon"></i></button>
  73. <button title="Back" class="ts icon tiny button" onclick="backDir();"><i class="arrow left icon"></i></button>
  74. <button title="Parent" class="ts icon tiny button" onclick="parentDir();"><i class="arrow up icon"></i></button>
  75. <button title="Refresh" class="ts icon tiny button" onclick="refresh();"><i class="refresh icon"></i></button>
  76. <button title="New Folder" class="ts icon tiny button" onclick="newFolder();"><i class="folder icon"></i></button>
  77. <div class="ts action fluid tiny input" style="width: calc(100% - 180px); float: right;">
  78. <input id="addressbar" type="text" placeholder="" onchange="updatePath();">
  79. <button class="ts positive icon button" onclick="confirmSelection();"><i class="checkmark icon"></i></button>
  80. </div>
  81. <div id="newfilenameInput" style="width:100%; margin-top:12px;" align="right">
  82. <div class="ts fluid tiny input" style="width: calc(100% - 180px); float: right;">
  83. <input id="filename" type="text" placeholder="New Filename">
  84. </div>
  85. </div>
  86. <div id="newFolderInput" style="width:100%; margin-top:4px; display:none;" align="right">
  87. <div class="ts fluid action tiny input" style="width: calc(100% - 180px); float: right;">
  88. <input id="foldername" type="text" placeholder="New Folder" value="">
  89. <button class="ts icon button" onclick="createFolder()" title="Create Folder"><i class="add icon"></i></button>
  90. </div>
  91. </div>
  92. </div>
  93. <div id="sidebar" class="ts left static visible overlapped sidebar" style="background-color:#f5f5f5 !important;z-index:90 !important; width:200px;">
  94. <div id="sidebarPadder" style="height:46px;"></div>
  95. <details class="ts accordion" open>
  96. <summary>
  97. <i class="dropdown icon"></i> <span locale="roots/user">User</span>
  98. </summary>
  99. <div class="content" >
  100. <div class="ts list" id="userlist">
  101. </div>
  102. </div>
  103. </details>
  104. <details class="ts accordion" open>
  105. <summary>
  106. <i class="dropdown icon"></i> <span locale="roots/storage">Storage</span>
  107. </summary>
  108. <div class="content">
  109. <div class="ts list" id="storagelist">
  110. </div>
  111. </div>
  112. </details>
  113. </div>
  114. <div class="pusher">
  115. <br>
  116. <div class="fileListWrapper" style="min-height:300px; width:100%;">
  117. <div id="folderList" class="ts segmented basic fluid list whiteTheme">
  118. <div class="fileObject">
  119. <span class="fileInfo"><i class="loading spinner icon" style="margin-right:12px;"></i> <span locale="message/loading">Loading</span></span>
  120. </div>
  121. </div>
  122. <div id="fileList" class="ts segmented fluid list whiteTheme">
  123. </div>
  124. </div>
  125. <br><br>
  126. </div>
  127. <div id="waitloader" class="ts active dimmer" style="display:none; z-index:999;">
  128. <div id="waitloadertext" class="ts indeterminate text loader" locale="message/waitingResp">Waiting Response</div>
  129. </div>
  130. <script>
  131. var multiSelect = false;
  132. var type = "file";
  133. var currentDir = "user:/";
  134. var currentFileList = [];
  135. var pathHistory = [];
  136. var ctrlDown = false;
  137. var shiftDown = false;
  138. var lastClickedItemID = 0;
  139. var listenerUUID = "";
  140. var fileOptions = {};
  141. if (applocale){
  142. //Applocale found. Do localization
  143. applocale.init("../locale/file_selector.json", function(){
  144. applocale.translate();
  145. initRoots();
  146. });
  147. }else{
  148. //Applocale not found. Is this a trim down version of ArozOS?
  149. applocale = {
  150. getString: function(key, original){
  151. return original;
  152. }
  153. }
  154. initRoots();
  155. }
  156. initSelectorObject();
  157. updateWindowResize();
  158. function initSelectorObject(){
  159. var initInfo = loadSelectorInfoFromHash();
  160. //Load the initiation directory
  161. listDir(initInfo.root);
  162. //init global var
  163. type = initInfo.type;
  164. multiSelect = initInfo.allowMultiple;
  165. listenerUUID = initInfo.listenerUUID;
  166. if (initInfo.options != undefined){
  167. fileOptions = JSON.parse(JSON.stringify(initInfo.options));
  168. }
  169. //Load options and parse the UI
  170. if (type == "new"){
  171. //Resize the top bar
  172. $("#sidebarPadder").css("height", "90px");
  173. $(".fileListWrapper").css("padding-top", "50px");
  174. if (typeof(fileOptions.defaultName) != "undefined"){
  175. $("#filename").val(fileOptions.defaultName);
  176. }else{
  177. $("#filename").val("newfile.txt");
  178. }
  179. }else{
  180. $("#newfilenameInput").hide();
  181. }
  182. }
  183. function cancelSelection(){
  184. localStorage.setItem(listenerUUID, JSON.stringify("&&selection_canceled&&"));
  185. }
  186. function confirmSelection(){
  187. var files = [];
  188. $(".selected.fileObject").each(function(){
  189. var filename = decodeURIComponent($(this).attr('filename'));
  190. var filepath = decodeURIComponent($(this).attr('filepath'));
  191. files.push({
  192. filename: filename,
  193. filepath: filepath
  194. });
  195. });
  196. //Check if currentdir end with "/". If not, append it
  197. if(currentDir.substr(currentDir.length - 1, 1) != "/"){
  198. currentDir = currentDir + "/";
  199. }
  200. //Check for special cases
  201. if (files.length == 0 && type == "folder"){
  202. //Select the current path as target instead
  203. var currentPathname = currentDir.split("/");
  204. currentPathname.pop();
  205. currentPathname = currentPathname.pop();
  206. if (currentPathname == ""){
  207. currentPathname = currentDir;
  208. }
  209. files.push({
  210. filename: currentPathname,
  211. filepath: currentDir
  212. });
  213. }else if (files.length == 0 && type == "new"){
  214. //Push this new file into the return structure
  215. var newFilename = $("#filename").val();
  216. files.push({
  217. filename: newFilename,
  218. filepath: currentDir + newFilename
  219. });
  220. }
  221. if (ao_module_virtualDesktop){
  222. if (!ao_module_parentCallback(files)){
  223. //Parent callback not exists
  224. alert("Selection Failed. Is parent window alive?")
  225. }else{
  226. parent.closeFwProcess(ao_module_windowID);
  227. }
  228. }else{
  229. if (listenerUUID == ""){
  230. alert("Invalid listener UUID. Please re-open your file selector.")
  231. return;
  232. }
  233. var selectedFilesInJSON = JSON.stringify(files);
  234. localStorage.setItem(listenerUUID, selectedFilesInJSON);
  235. $("#waitloader").show();
  236. $(".pusher").css("overflow","hidden");
  237. setTimeout(function(){
  238. $("#waitloadertext").html("<i class='remove icon'></i> System is not responding. <br>Please close this window and retry.");
  239. },10000)
  240. }
  241. }
  242. //Handle on window close function, cancel current selection
  243. window.onbeforeunload = function(){
  244. cancelSelection();
  245. }
  246. //Overwrite the ao_module close function
  247. function ao_module_close(){
  248. if (!ao_module_virtualDesktop){
  249. return;
  250. }
  251. if (!ao_module_parentCallback(files)){
  252. alert("Selection Failed. Is parent window alive?")
  253. }else{
  254. parent.closeFwProcess(ao_module_windowID);
  255. }
  256. }
  257. function updatePath(){
  258. var newDir = $("#addressbar").val();
  259. listDir(newDir);
  260. }
  261. function refresh(){
  262. $("#fileList").html("");
  263. $("#folderList").html("");
  264. listDir(currentDir);
  265. }
  266. function newFolder(){
  267. var newFileOffset = 0;
  268. if ($("#newfilenameInput").is(":visible")){
  269. newFileOffset += 40;
  270. }
  271. $("#newFolderInput").toggle();
  272. if($("#newFolderInput").is(":visible")){
  273. $("#sidebarPadder").css("height", 90 + newFileOffset + "px");
  274. }else{
  275. $("#sidebarPadder").css("height", 46 + newFileOffset + "px");
  276. }
  277. updateFileListTopLocation();
  278. }
  279. function hideFolderNameInput(){
  280. $("#newFolderInput").hide();
  281. $("#sidebarPadder").css("height", "46px");
  282. $(".fileListWrapper").css("padding-top", "0px");
  283. }
  284. function createFolder(){
  285. var folderName = $("#foldername").val();
  286. if (folderName == ""){
  287. folderName = "New Folder"
  288. $("#foldername").val("New Folder");
  289. }
  290. folderName = folderName.replace(/[<>:"/\\|?*]/g, "_");
  291. //Check if folder exists
  292. var nameAlreadyExists = false;
  293. currentFileList.forEach(fileObject => {
  294. if (fileObject.IsDir && fileObject.Filename == folderName){
  295. nameAlreadyExists = true;
  296. }
  297. });
  298. if (nameAlreadyExists){
  299. alert("Folder already exists")
  300. return
  301. }
  302. //Create the new folder request
  303. requestCSRFToken(function(token){
  304. $.ajax({
  305. url: "../../system/file_system/newItem",
  306. data: {type: "folder", src: currentDir, filename: folderName, csrft: token},
  307. success: function(data){
  308. if (data.error !== undefined){
  309. alert(data.error);
  310. }else{
  311. refresh()
  312. }
  313. hideFolderNameInput();
  314. }
  315. });
  316. });
  317. }
  318. function loadSelectorInfoFromHash(){
  319. if (window.location.hash.length == 0){
  320. return {
  321. root: "user:/",
  322. type: "file",
  323. allowMultiple: false
  324. }
  325. }else{
  326. try{
  327. var selectInfo = JSON.parse(decodeURIComponent(window.location.hash.substring(1)));
  328. return selectInfo;
  329. }catch{
  330. //Error parsing the input. Use default settings
  331. return {
  332. root: "user:/",
  333. type: "file",
  334. allowMultiple: false
  335. }
  336. }
  337. }
  338. }
  339. function listDir(dir){
  340. currentDir = dir;
  341. pathHistory.push(currentDir);
  342. $("#addressbar").val(currentDir);
  343. ao_module_setWindowTitle(`Open`);
  344. $.get("../../system/file_system/listDir?dir=" + encodeURIComponent(dir),function(data){
  345. $("#folderList").html("");
  346. $("#fileList").html("");
  347. if (data === null){
  348. $("#folderList").hide();
  349. $("#fileList").hide();
  350. return;
  351. }else{
  352. $("#folderList").show();
  353. $("#fileList").show();
  354. }
  355. if (data.error !== undefined){
  356. //Load the index instead
  357. listDir("user:/");
  358. }else{
  359. currentFileList = data;
  360. var folders = [];
  361. var files = [];
  362. for (var i =0; i < data.length; i++){
  363. if (data[i].IsDir == true){
  364. folders.push(data[i]);
  365. }else{
  366. if (fileOptions.filter != undefined){
  367. var fileExt = data[i].Filename.split(".").pop();
  368. for (var j = 0; j < fileOptions.filter.length; j++){
  369. if (fileOptions.filter[j] == fileExt){
  370. files.push(data[i]);
  371. break;
  372. }
  373. }
  374. }else{
  375. files.push(data[i]);
  376. }
  377. }
  378. }
  379. //Append folder first then files
  380. var count = 0;
  381. for (var i =0; i < folders.length; i++){
  382. var filename = folders[i].Filename;
  383. var filepath = folders[i].Filepath;
  384. var ext = filename.split(".").pop();
  385. var icon = ao_module_utils.getIconFromExt(ext);
  386. var isDir = folders[i].IsDir;
  387. if (isDir == true){
  388. icon = "folder";
  389. }
  390. var fileSize = folders[i].Displaysize;
  391. $("#folderList").append(`<div class="fileObject item" fid="${count}" ondblclick="openFolder(event,this);" onclick="selectThis(this,event);" filepath="${encodeURIComponent(filepath)}" filename="${encodeURIComponent(filename)}" isDir="${isDir}">
  392. <span class="fileInfo"><i class="${icon} icon" style="margin-right:4px;"></i> ${filename}</span>
  393. </div>`);
  394. count++;
  395. }
  396. if (folders.length == 0){
  397. $("#folderList").hide();
  398. }
  399. for (var i =0; i < files.length; i++){
  400. var filename = files[i].Filename;
  401. var filepath = files[i].Filepath;
  402. var ext = filename.split(".").pop();
  403. var icon = ao_module_utils.getIconFromExt(ext);
  404. var isDir = files[i].IsDir;
  405. if (isDir == true){
  406. icon = "folder";
  407. }
  408. var fileSize = files[i].Displaysize;
  409. $("#fileList").append(`<div class="fileObject item" fid="${count}" ondblclick="chooseThisFile(this);" onclick="selectThis(this,event);" filepath="${encodeURIComponent(filepath)}" filename="${encodeURIComponent(filename)}" isDir="${isDir}">
  410. <span class="fileInfo"><i class="${icon} icon" style="margin-right:4px;margin-top: 2px;"></i> ${filename}</span>
  411. </div>`);
  412. count++;
  413. }
  414. if (files.length == 0){
  415. $("#fileList").hide();
  416. }
  417. $('.pusher').scrollTop(0);
  418. }
  419. });
  420. }
  421. function requestCSRFToken(callback){
  422. $.ajax({
  423. url: "../../system/csrf/new",
  424. success: function(token){
  425. callback(token);
  426. }
  427. })
  428. }
  429. //Open folder
  430. function openFolder(event, object){
  431. event.preventDefault();
  432. var filepath = $(object).attr("filepath");
  433. filepath = decodeURIComponent(filepath);
  434. listDir(filepath);
  435. }
  436. function selectThis(object,event){
  437. //event.preventDefault();
  438. //event.stopImmediatePropagation();
  439. //Check if this object is in suitable selection type
  440. if ($(object).attr("IsDir") == "true" && type == "file"){
  441. return;
  442. }else if ($(object).attr("IsDir") == "false" && type == "folder"){
  443. return;
  444. }else if (type == "new" && $(object).attr("IsDir") == "false"){
  445. //Use this filename as the newfile name (aka overwrite mode)
  446. var newNewFilename = $(object).attr("filename");
  447. newNewFilename = decodeURIComponent(newNewFilename);
  448. $("#filename").val(newNewFilename);
  449. return;
  450. }else if (type == "new" && $(object).attr("IsDir") == "true"){
  451. //Selected a folder in new mode. Ignore it
  452. return
  453. }
  454. if (multiSelect){
  455. if (ctrlDown){
  456. //Add this into selection list
  457. $(object).addClass("selected");
  458. }else if (shiftDown){
  459. var start = lastClickedItemID;
  460. var end = $(object).attr("fid");
  461. if (start > end){
  462. start = end;
  463. end = lastClickedItemID;
  464. }
  465. var fileObjects = $(".fileObject");
  466. for (var k = start; k <= end; k++){
  467. $(fileObjects[k]).addClass("selected");
  468. }
  469. }else{
  470. //Reset and add this into selection list
  471. $(".selected").removeClass("selected");
  472. $(object).addClass("selected");
  473. }
  474. }else{
  475. $(".selected").removeClass("selected");
  476. $(object).addClass("selected");
  477. }
  478. //Update last selected id
  479. lastClickedItemID = $(object).attr('fid');
  480. //Update title
  481. var objectCount = $(".selected").length;
  482. var typeName = "object"
  483. if (type == "file"){
  484. typeName = "file";
  485. }else if (type == "folder"){
  486. typeName = "folder";
  487. }
  488. var desc = `${typeName} selected`;
  489. if (objectCount > 1){
  490. desc = `${typeName + "s"} selected`;
  491. }
  492. ao_module_setWindowTitle(`Open (${objectCount} ${desc})`);
  493. }
  494. $(window).on("keydown",function(event){
  495. if (event.which == 17){
  496. ctrlDown = true;
  497. }else if (event.which == 16){
  498. shiftDown = true;
  499. }
  500. });
  501. $(window).on("keyup",function(event){
  502. if (event.which == 17){
  503. ctrlDown = false;
  504. }else if (event.which == 16){
  505. shiftDown = false;
  506. }
  507. });
  508. $(window).on("resize",function(){
  509. updateWindowResize();
  510. });
  511. function updateWindowResize(){
  512. if (window.innerWidth < 560){
  513. //Mobile mode
  514. $("#sidebar").attr("class", "ts left overlapped sidebar");
  515. $(".pusher").css("margin-left", "0px").css("width","100%");
  516. $("#sidebar").css("margin-top", "30px");
  517. $("#sidebarToggleBtn").show();
  518. $("#addressbar").parent().css({
  519. "width": "100%",
  520. "margin-top": "4px"
  521. });
  522. $("#newfilenameInput").find(".input").css({
  523. "width": "100%",
  524. "margin-top": "4px"
  525. });
  526. $("#newFolderInput").find(".input").css({
  527. "width": "100%",
  528. "margin-top": "4px"
  529. });
  530. }else{
  531. $("#sidebar").attr("class", "ts left static visible overlapped sidebar");
  532. $(".pusher").css("margin-left", "200px").css("width","calc(100% - 200px)");
  533. $("#sidebarToggleBtn").hide();
  534. $("#sidebar").css("margin-top", "0px");
  535. $("#addressbar").parent().css({
  536. "width": "calc(100% - 180px)",
  537. "margin-top": "0px"
  538. });
  539. $("#newfilenameInput").find(".input").css({
  540. "width": "calc(100% - 180px)",
  541. "margin-top": "0px"
  542. });
  543. $("#newFolderInput").find(".input").css({
  544. "width": "calc(100% - 180px)",
  545. "margin-top": "8px"
  546. });
  547. }
  548. updateFileListTopLocation();
  549. }
  550. function updateFileListTopLocation(){
  551. $(".fileListWrapper").css("padding-top", $(".navi").height() - 38 + "px");
  552. }
  553. function initAddressBarWidth(){
  554. $("#addressbar").css("width",window.innerWidth - 220 + "px");
  555. }
  556. function chooseThisFile(object){
  557. $(".selected").removeClass('selected');
  558. $(object).addClass('selected');
  559. confirmSelection();
  560. }
  561. function parentDir(){
  562. if (currentDir.substring(currentDir.length - 1) == "/"){
  563. currentDir = currentDir.substring(0, currentDir.length - 1);
  564. }
  565. var tmp = currentDir.split("/");
  566. tmp.pop();
  567. var parentPath = tmp.join("/");
  568. if (parentPath.length == 0){
  569. //Do nothing. Already at root dir
  570. }else{
  571. listDir(parentPath);
  572. }
  573. }
  574. function backDir(){
  575. if (pathHistory.length > 1){
  576. pathHistory.pop();
  577. var targetPath = pathHistory.pop();
  578. listDir(targetPath);
  579. }
  580. }
  581. //Initialize user shortcuts
  582. function initRoots(){
  583. $.get("../../system/file_system/listRoots",function(data){
  584. $("#storagelist").html("");
  585. for (var i =0; i < data.length; i++){
  586. $('#storagelist').append(`<div class="item extrapadding" filepath="${data[i]["RootPath"]}" onclick="openShortcut(this);"><i class="disk outline icon" style="margin-right:8px;"></i> ${data[i]["RootName"]} (${data[i]["RootPath"]})</div>`);
  587. }
  588. });
  589. $.get("../../system/file_system/listRoots?user=true",function(data){
  590. $("#userlist").html("");
  591. for (var i =0; i < data.length; i++){
  592. if (data[i].IsDir == true){
  593. if (data[i]["Filename"].substring(0,1) == "."){
  594. //Do not show hidden files
  595. continue;
  596. }
  597. //Get the icon and the localization of this user root
  598. var iconAndFolderName = getUserRootIcons(data[i]["Filename"]);
  599. console.log(iconAndFolderName);
  600. $('#userlist').append(`<div class="item extrapadding" filepath="${data[i]["Filepath"]}" onclick="openShortcut(this);"><i class="${iconAndFolderName[0]} icon" style="margin-right:8px;"></i> ${iconAndFolderName[1]}</div>`);
  601. }
  602. }
  603. });
  604. }
  605. function getUserRootIcons(foldername){
  606. var icon = "folder open";
  607. var name = foldername;
  608. foldername = foldername.toLowerCase();
  609. if (foldername == "desktop"){
  610. icon = "computer";
  611. name = applocale.getString("sidebar/vroot/desktop", name);
  612. }else if (foldername == "document"){
  613. icon = "file text outline";
  614. name = applocale.getString("sidebar/vroot/document", name);
  615. }else if (foldername == "music" || foldername == "audio"){
  616. icon = "music";
  617. name = applocale.getString("sidebar/vroot/music", name);
  618. }else if (foldername == "photo" || foldername == "picture"){
  619. icon = "image";
  620. name = applocale.getString("sidebar/vroot/photo", name);
  621. }else if (foldername == "video" || foldername == "film"){
  622. icon = "video";
  623. name = applocale.getString("sidebar/vroot/video", name);
  624. }else if (foldername == "trash" || foldername == "bin" || foldername == "rubbish"){
  625. icon = "trash"
  626. name = applocale.getString("sidebar/vroot/trash", name);
  627. }else if (foldername == "download"){
  628. icon = "download"
  629. name = applocale.getString("sidebar/vroot/download", name);
  630. }else if (foldername == "www" || foldername == "web" || foldername == "mysite"){
  631. icon = "globe"
  632. name = applocale.getString("sidebar/vroot/web", name);
  633. }else if (foldername == "model"){
  634. icon = "cube"
  635. name = applocale.getString("sidebar/vroot/model", name);
  636. }else if (foldername == "appdata"){
  637. icon = "code"
  638. name = applocale.getString("sidebar/vroot/appdata", name);
  639. }
  640. return [icon, name];
  641. }
  642. function openShortcut(object){
  643. var targetdir = $(object).attr("filepath");
  644. targetdir = decodeURIComponent(targetdir);
  645. listDir(targetdir);
  646. if (window.innerWidth < 560){
  647. ts('.sidebar').sidebar('hide');
  648. }
  649. }
  650. </script>
  651. </body>
  652. </html>