Skip to content

Instantly share code, notes, and snippets.

@jcubic
Last active November 30, 2022 22:26
Show Gist options
  • Save jcubic/4e4b2d7663dfad04913a3ad60da6158a to your computer and use it in GitHub Desktop.
Save jcubic/4e4b2d7663dfad04913a3ad60da6158a to your computer and use it in GitHub Desktop.
File Explorer in jQuery UI dialog with Editor
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>File Explorer using jQuery UI</title>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="http://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>
<script src="jquery.filebrowser/js/jquery.filebrowser-src.js"></script>
<script src="json-rpc/json-rpc.js"></script>
<script src="codemirror/lib/codemirror.js"></script>
<script src="codemirror/keymap/emacs.js"></script>
<script src="script.js"></script>
<link href="jquery.filebrowser/css/jquery.filebrowser-src.css" rel="stylesheet"/>
<link href="codemirror/lib/codemirror.css" rel="stylesheet"/>
<link href="codemirror/theme/base16-dark.css" rel="stylesheet"/>
<link href="http://code.jquery.com/ui/1.12.1/themes/dark-hive/jquery-ui.css" rel="stylesheet"/>
<link href="style.css" rel="stylesheet"/>
$(function() {
rpc({
url: 'service.php',
promisify: true
}).then(function(service) {
var editors = [];
service.username().then(function(username) {
var browser = $('<div/>').appendTo('body').dialog({
width: 800,
height: 600
}).browse({
root: '/home/' + username + '/projects/jcubic/terminal/repo/',
dir: function(path) {
return service.ls(path);
},
open: function(path) {
var fname = path.replace(/.*\//, '');
var readonly = true;
var mtime;
service.is_writable(path).then(function(is_writable) {
readonly = !is_writable;
});
service.filemtime(path).then(function(time) {
mtime = time;
});
var ext = fname.replace(/^.*\./, '');
var mode;
// you can add more modes here:
switch(ext) {
case 'js':
mode = 'javascript';
break;
case 'rb':
mode = 'ruby';
break;
case 'py':
mode = 'python';
break;
case 'sql':
mode = 'mysql';
break;
case 'svg':
mode = 'xml';
break;
case 'xml':
case 'css':
case 'php':
mode = ext;
break;
}
var scripts = $('script').map(function() {
return ($(this).attr('src') || '').replace(/.*\//, '');
}).get();
if (scripts.indexOf(mode + '.js') == -1) {
var name = 'codemirror-5.29.0/mode/' + mode + '/' + mode + '.js';
service.file_exists(name).then(function(exists) {
if (exists) {
$('<script/>').attr('src', name).appendTo('head');
}
});
}
service.file(path).then(function(content) {
var unsaved = false;
var div = $('<div><textarea/></div>');
var textarea = div.find('textarea').hide();
textarea.val(content);
div.dialog({
title: fname,
width: 650,
beforeClose: function(e, ui) {
//e.preventDefault();
//e.stopPropagation();
//$(this).dialog('open');
if (unsaved) {
if (confirm('Unsaved file, are you sure?')) {
$(this).dialog('destroy');
} else {
return false;
}
} else {
$(this).dialog('destroy');
}
},
resize: function(e, ui) {
// codemirror have no api for resize
console.log(div.height());
editor.editor.setSize(textarea.width(), textarea.height());
}
});
var editor = {
dialog: div,
editor: CodeMirror.fromTextArea(textarea[0], {
lineNumbers: true,
matchBrackets: true,
mode: mode,
readOnly: readonly,
theme: 'base16-dark',
indentUnit: 4,
keyMap: 'emacs',
extraKeys: {
"Ctrl-S": function(cm) {
if (unsaved) {
function saveFile() {
editor.editor.save();
var content = textarea.val();
service.save(path, content).then(function() {
unsaved = false;
div.dialog('option', 'title', fname);
});
}
service.filemtime(path).then(function(time) {
if (mtime != time) {
if (confirm('File `' + fname + '\' changed ' +
'on Disk are you sure?')) {
saveFile();
}
} else {
saveFile();
}
});
}
},
"Tab": "indentAuto",
"fallthrough": "default"
}
})
};
editor.editor.on('change', function(editor) {
console.log('change');
unsaved = true;
div.dialog('option', 'title', '*' + fname);
});
editors.push(editor);
});
}
});
});
});
});
<?php
require('json-rpc/json-rpc.php');
class Service {
function file_exists($path) {
return file_exists($path);
}
function username() {
return get_current_user();
}
function is_writable($path) {
return is_writable($path);
}
function file($path) {
return file_get_contents($path);
}
function save($path, $content) {
$file = fopen($path, 'w');
$ret = fwrite($file, $content);
fclose($file);
return $ret;
}
function filemtime($path) {
return filemtime($path);
}
function ls($path) {
$files = array();
$dirs = array();
foreach (new DirectoryIterator($path) as $file) {
$name = $file->getBasename();
if ($name != "." && $name != "..") {
if ($file->isFile() || $file->isLink()) {
$files[] = $name;
} else {
$dirs[] = $name;
}
}
}
return array(
"files" => $files,
"dirs" => $dirs
);
}
}
echo handle_json_rpc(new Service());
?>
body {
font-size: 10px;
}
.ui-dialog .ui-dialog-content {
padding: 0;
overflow: hidden;
}
.browser {
width: 800px;
height: 600px;
}
.browser-widget .content .selection {
border-color: #fff;
}
.browser-widget li.file,
.browser-widget li.directory {
width: 60px;
}
.ui-dialog textarea {
width: 100%;
height: 100%;
padding: 0;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
resize: none;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment