Add server file picker to TinyMCE (close #20)
This commit is contained in:
parent
b1edda1f86
commit
7072d4c343
112
lib/filepicker.php
Normal file
112
lib/filepicker.php
Normal file
@ -0,0 +1,112 @@
|
||||
<?php
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
require_once __DIR__ . '/../required.php';
|
||||
|
||||
dieifnotloggedin();
|
||||
|
||||
include_once __DIR__ . "/../lib/mimetypes.php";
|
||||
|
||||
$base = FILE_UPLOAD_PATH;
|
||||
|
||||
$folder = "";
|
||||
if (isset($VARS['path']) && file_exists($base . $VARS['path']) && strpos(realpath($base . $VARS['path']), FILE_UPLOAD_PATH) === 0) {
|
||||
$folder = $VARS['path'];
|
||||
}
|
||||
|
||||
if ($folder == "/") {
|
||||
$folder = "";
|
||||
}
|
||||
|
||||
$fullpath = $base . $folder;
|
||||
?>
|
||||
|
||||
<div class="mb-2">
|
||||
<nav aria-label="breadcrumb" class="my-auto">
|
||||
<ol class="breadcrumb m-0">
|
||||
<?php
|
||||
$pathparts = explode("/", "$folder");
|
||||
$pstr = "";
|
||||
for ($i = 0; $i < count($pathparts); $i++) {
|
||||
$p = $pathparts[$i];
|
||||
$pstr .= "/$p";
|
||||
$pstr = "/" . ltrim($pstr, "/");
|
||||
if ($i == 0) {
|
||||
$p = "<span class=\"fas fa-home\"></span>";
|
||||
}
|
||||
if ($i == count($pathparts) - 1) {
|
||||
echo "\t<li aria-current=\"page\" class=\"breadcrumb-item active\">$p</li>";
|
||||
} else {
|
||||
echo "\t<li class=\"breadcrumb-item\"><span class=\"filepicker-item\" data-type=\"dir\" data-path=\"$pstr\">$p</a></li>";
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
?>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="list-group">
|
||||
<?php
|
||||
$files = scandir($fullpath);
|
||||
$count = 0;
|
||||
foreach ($files as $f) {
|
||||
if (strpos($f, '.') !== 0) {
|
||||
$count++;
|
||||
$link = "$folder/$f";
|
||||
$target = "_BLANK";
|
||||
$isdir = false;
|
||||
$icon = "fas fa-file";
|
||||
if (is_dir($fullpath . "/" . $f)) {
|
||||
$isdir = true;
|
||||
$link = "app.php?page=files&path=$folder/$f";
|
||||
$icon = "fas fa-folder";
|
||||
$target = "";
|
||||
} else {
|
||||
$link = "public/file.php?file=$folder/$f";
|
||||
$extension = pathinfo($fullpath . "/" . $f)['extension'];
|
||||
// If we don't have an extension, try using the whole filename
|
||||
if ($extension == "") {
|
||||
$extension = $f;
|
||||
}
|
||||
$mimetype = "application/octet-stream";
|
||||
// Lookup mimetype from extension
|
||||
if (array_key_exists($extension, $EXT2MIME)) {
|
||||
$mimetype = $EXT2MIME[$extension];
|
||||
}
|
||||
// Lookup icon from mimetype
|
||||
if (array_key_exists($mimetype, $MIMEICONS)) {
|
||||
$icon = $MIMEICONS[$mimetype];
|
||||
} else { // Allow broad generic <format>/other icons
|
||||
$mimefirst = explode("/", $mimetype, 2)[0];
|
||||
if (array_key_exists($mimefirst . "/other", $MIMEICONS)) {
|
||||
$icon = $MIMEICONS[$mimetype];
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<div
|
||||
class="list-group-item filepicker-item"
|
||||
data-type="<?php echo $isdir ? "dir" : "file" ?>"
|
||||
data-path="<?php echo "$folder/$f"; ?>"
|
||||
data-file="<?php echo $f; ?>">
|
||||
<span class="<?php echo $icon; ?> fa-fw"></span> <?php echo $f; ?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
if ($count == 0) {
|
||||
?>
|
||||
<div class="list-group-item text-center">
|
||||
<p class="text-muted">
|
||||
<i class="far fa-folder-open fa-5x fa-fw"></i>
|
||||
</p>
|
||||
<p class="h5 text-muted">
|
||||
<?php lang("nothing here"); ?>
|
||||
</p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</div>
|
@ -40,7 +40,8 @@ define("PAGES", [
|
||||
"title" => "editor",
|
||||
"styles" => [
|
||||
"static/css/editorparent.css",
|
||||
"static/css/iconselector.css"
|
||||
"static/css/iconselector.css",
|
||||
"static/css/filepicker.css",
|
||||
],
|
||||
"scripts" => [
|
||||
"static/js/editorparent.js",
|
||||
|
@ -68,6 +68,25 @@ if (!is_empty($VARS['siteid'])) {
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="modal fade" id="fileBrowseModal" tabindex="-1" role="dialog" aria-labelledby="fileBrowseLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="fileBrowseLabel"><i class="far fa-folder-open"></i> <?php lang("browse"); ?></h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body" id="fileBrowseModalBody">
|
||||
<i class="fas fa-spin fa-circle-notch"></i> <?php lang("loading"); ?>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal"><?php lang("cancel"); ?></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="pageSettingsModal" tabindex="-1" role="dialog" aria-labelledby="pageSettingsLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<form class="modal-content" action="action.php" method="POST">
|
||||
|
10
static/css/filepicker.css
Normal file
10
static/css/filepicker.css
Normal file
@ -0,0 +1,10 @@
|
||||
/*
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.filepicker-item {
|
||||
cursor: pointer;
|
||||
color: #2196F3;
|
||||
}
|
@ -31,6 +31,8 @@ function saveEdits() {
|
||||
parent.postMessage('save ' + json, "*");
|
||||
}
|
||||
|
||||
var filePickerCallback = null;
|
||||
|
||||
$(document).ready(function () {
|
||||
$('a').click(function (e) {
|
||||
e.preventDefault();
|
||||
@ -46,25 +48,22 @@ $(document).ready(function () {
|
||||
tinymce.init({
|
||||
selector: '.sw-editable',
|
||||
inline: true,
|
||||
paste_data_images: true,
|
||||
plugins: [
|
||||
'autolink lists link image imagetools charmap',
|
||||
'searchreplace visualblocks code fullscreen',
|
||||
'media table contextmenu paste code'
|
||||
],
|
||||
branding: false,
|
||||
/*menu: {
|
||||
edit: {title: 'Edit', items: 'undo redo | cut copy paste pastetext | selectall | findreplace'},
|
||||
view: {title: 'View', items: 'sourcecode | visualaid showblocks'},
|
||||
insert: {title: 'Insert', items: 'image link media table | charmap'},
|
||||
format: {title: 'Format', items: 'bold italic underline strikethrough superscript subscript | blocks align formats | removeformat'},
|
||||
table: {title: 'Table', items: 'inserttable tableprops deletetable | cell row column'}
|
||||
},*/
|
||||
elementpath: false,
|
||||
menubar: 'edit insert view format table tools',
|
||||
toolbar: 'insert | undo redo | formatselect | bold italic | bullist numlist outdent indent | removeformat | fullscreen',
|
||||
link_list: function (success) {
|
||||
success(pages_list);
|
||||
},
|
||||
file_picker_callback: function (callback, value, meta) {
|
||||
filePickerCallback = callback;
|
||||
parent.postMessage('browse ' + meta.filetype, "*");
|
||||
},
|
||||
mobile: {
|
||||
theme: 'mobile'
|
||||
}
|
||||
@ -114,6 +113,10 @@ $(document).ready(function () {
|
||||
var comp = json["component"];
|
||||
var data = json["content"];
|
||||
$(".sw-complex[data-component='" + comp + "']").data("json", JSON.stringify(data));
|
||||
} else if (event.data.startsWith("picked ")) {
|
||||
var json = JSON.parse(event.data.slice(7));
|
||||
console.log(json);
|
||||
filePickerCallback(json.path, json.meta);
|
||||
}
|
||||
});
|
||||
});
|
@ -78,6 +78,34 @@ function editComplex(json) {
|
||||
$("#editModal").modal();
|
||||
}
|
||||
|
||||
function loadFilePickerFolder(path) {
|
||||
$.get("lib/filepicker.php", {
|
||||
path: path
|
||||
}, function (data) {
|
||||
$("#fileBrowseModalBody").html(data);
|
||||
$(".filepicker-item").click(function () {
|
||||
if ($(this).data("type") == "dir") {
|
||||
loadFilePickerFolder($(this).data("path"));
|
||||
} else {
|
||||
var path = "file.php?file=" + $(this).data("path");
|
||||
var data = {
|
||||
path: path,
|
||||
meta: {}
|
||||
};
|
||||
json = JSON.stringify(data);
|
||||
document.getElementById("editorframe").contentWindow.postMessage("picked " + json, "*");
|
||||
$("#fileBrowseModal").modal('hide');
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function openFilePicker(type) {
|
||||
loadFilePickerFolder("/");
|
||||
$("#fileBrowseModal").modal();
|
||||
}
|
||||
|
||||
|
||||
$("#editModalSave").on("click", function () {
|
||||
var data = {};
|
||||
data["component"] = $("#editModal").data("component");
|
||||
@ -102,6 +130,8 @@ window.addEventListener('message', function (event) {
|
||||
save(event.data.slice(5));
|
||||
} else if (event.data.startsWith("editcomplex ")) {
|
||||
editComplex(event.data.slice(12));
|
||||
} else if (event.data.startsWith("browse ")) {
|
||||
openFilePicker(event.data.slice(7));
|
||||
}
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user