Сейчас у меня возникла необходимость показывать на странице пользователю диалог, в котором о мог бы выбрать файл, находящийся на файловой системе сервера. Немного погуглив нашёл несколько решений и примеров для jquery, которые показались мне просто ужасными и я решил, что сделать собственное решение будет значительно проще и быстрее. Как оказалось, делается оно почти тривиально.
Полученное мною решение состоит из трёх частей: шаблон cl-closure-template для генерации контента на стороне клиента, несколько строк кода на JavaScript для управления и серверная часть, которая возвращает информацию о файловой системе.
Модуль restas-directory-publisher умеет собирать информацию о файловой системе, но по умолчанию возвращаёт её в формате html, а мне для данной задачи нужно в формате JSON. Исправить этот недостаток можно так:
(defun encode-json (obj)Здесь производится настройка подключения субмодуля и с переменной restas.directory-publisher:*autoindex-template*, используемой для генерации контента, связывается функция #'encode-json (реализацию данной функции я уже приводил ранее).
(flet ((encode-json-list (list stream)
(if (keywordp (car list))
(json:encode-json-plist list stream)
(json::encode-json-list-guessing-encoder list stream))))
(let ((json::*json-list-encoder-fn* #'encode-json-list))
(json:encode-json-to-string obj))))
(restas:mount-submodule -file-system- (#:restas.directory-publisher)
(restas.directory-publisher:*baseurl* '("api"))
(restas.directory-publisher:*directory* #P"/")
(restas.directory-publisher:*autoindex* t)
(restas.directory-publisher:*autoindex-template* #'encode-json))
Шаблон для генерации разметки:
{template directoryBrowse}Я лишь немного модифицировал шаблон, используемый в restas-directory-publisher
<table summary="Directory Listing" cellpadding="0" cellspacing="0">
<thead>
<tr>
<th class="n">Name</th>
<th class="m">Last Modified</th>
<th class="s">Size</th>
<th class="t">Type</th></tr>
</thead>
<tbody>
{if $parent}
<tr>
<td class="n">
<span class="directory" href="{$parent}">Parent Directory</span>
</td>
<td class="m"> </td>
<td class="s">- </td>
<td class="t">Directory</td>
</tr>
{/if}
{foreach $path in $paths}
<tr>
<td class="n">
<span class="{$path.type == 'Directory' ? 'directory' : 'file'}" href="{$path.href}">
{$path.name}
</span>
{nil}
{if $path.type == 'Directory'}/{/if}
</td>
<td class="m">{$path.lastModified}</td>
<td class="s">{$path.size ? $path.size : '- ' |noAutoescape}</td>
<td class="t">{$path.type}</td>
</tr>
{/foreach}
</tbody>
</table>
{/template}
Управлящий код на JavaScript совсем прост:
$(document).ready( function () { browse("/api/"); } );Я организовал этот код в виде отдельного законченного примера jsBrowser, который включил в состав restas-directory-publisher, посмотреть исходный код можно здесь
function browse (url) {
function directoryClick (evt) {
browse($(evt.currentTarget).attr("href"));
}
function fileClick (evt) {
$("h1").html(decodeURI($(evt.currentTarget).attr("href")));
}
function handler (data) {
$("#content").html(restas.jsBrowser.view.directoryBrowse(data));
$("#content .directory").click(directoryClick);
$("#content .file").click(fileClick);
}
$.getJSON(url, handler);
}
Комментариев нет:
Отправить комментарий