![Oracle Drags Its Feet in the JavaScript Trademark Dispute](https://cdn.sanity.io/images/cgdhsj6q/production/919c3b22c24f93884c548d60cbb338e819ff2435-1024x1024.webp?w=400&fit=max&auto=format)
Security News
Oracle Drags Its Feet in the JavaScript Trademark Dispute
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
custom-file-tree
Advanced tools
This is an HTML custom element for adding file tree visualisation and interaction to your page.
Simply add the element .js and .css files to your page using plain HTML:
<script src="somewhere/file-tree.esm.js" type="module" async></script>
<link rel="stylesheet" href="somewhere/file-tree.css" async />
And then you can work with any <file-tree>
like you would any other HTML element. For example:
// query select, or really any normal way to get an element handle:
const fileTree = document.querySelector(`file-tree`);
// Tell the file tree which files exist
fileTree.setFiles([
`README.md`,
`dist/client.bundle.js`,
`src/server/index.js`,
`LICENSE.md`,
`src/client/index.js`,
`src/server/middleware.js`,
`package.json`,
`dist/client.bundle.min.js`,
]);
After which users can play with the file tree as much as they like: all operations generate "permission-seeking" events, which need to be explicitly granted before the filetree will let them happen, meaning that you have code like:
filetree.addEventListener(`file:rename`, async ({ detail }) => {
const { oldPath, newPath, grant } = detail;
// we'll have the API determine whether this operation is allowed or not:
const result = await api.renameFile(oldPath, newPath);
if (result.error) {
warnUser(`An error occurred trying to rename ${oldPath} to ${newPath}.`);
} else if (result.denied) {
warnUser(`You do not have permission to rename files.`);
} else {
grant();
}
});
Thus ensuring that the file tree stays in sync with your real filesystem (whether that's through an api as in the example, or a client-side )
There is a live demo that shows off the above, with event handling set up to blanket-allow every action a user can take.
Part of the functionality for this element is based on the HTML5 drag-and-drop API (for parts of the file tree itself, as well as dragging files and folders into it from your device), which is notoriously based on "mouse events" rather than "pointer events", meaning there is no touch support out of the box.
However, touch support can be trivially achieved using the following shim, which has its own repository over on https://github.com/pomax/dragdroptouch (which is a fork of https://github.com/Bernardo-Castilho/dragdroptouch, rewritten as a modern ESM with support for autoloading)
<script
src="https://pomax.github.io/dragdroptouch/dist/drag-drop-touch.esm.min.js?autoload"
type="module"
></script>
Load this as first thing on your page, and done: drag-and-drop using touch will now work.
As mentioned above, events are "permission seeking", meaning that they are dispatched before an action is allowed to take place. Your event listener code is responsible for deciding whether or not that action is allowed to take place given the full context of who's performing it on which file/directory.
If an event is not allowed to happen, your code can simply exit the event handler. The file-tree will remain as it was before the user tried to manipulate it.
If an event is allowed to happen, your code must call event.detail.grant()
, which lets the file tree perform the associated action.
Events are listed here as name → detail object content
, with the grant
function omitted from the detail object, as by definition all events come with a grant function.
file:click
→ {path}
,path
representing the full path of the file in question.selected
class to the associated file entry.file:create
→ {path, content?}
,path
being the file's full path. If this file was created through a file "upload", it will also have a content
value of type ArrayBuffer representing the file's byte code.path
value.file:rename
→ {oldPath, newPath}
,oldPath
being the current file path, and newPath
the desired new path.../
) should be effected by just moving the file to the correct directory.file:move
→ {oldPath, newPath}
,oldPath
being the current file path, and newPath
the desired new path.newPath
.file:delete
→ {path}
,path
representing the full path of the file in question.<file-tree>
specifies the remove-empty
attribute, the now empty directory will also be deleted, gated by a dir:delete
permission event, but not gated by a confirm()
dialog to the user.The following events will be emitted when certain errors occur. All errors have an event detail object that is the same as for the non-error event, with an additional error
property that has a string value reflecting what went wrong.
file:create:error
,file:rename:error
,file:move:error
,dir:click
→ {path}
,path
representing the full path of the directory in question.selected
class to the associated directory entry.dir:toggle
→ {path, currentState}
,path
representing the full path of the directory in question, and currentState
reflecting whether this directory is currently visualized as "open"
or "closed"
, determined by whether or not its class list includes the closed
class.closed
class on the associated directory entry.dir:create
→ {path}
,path
being the directory's full path.path
value.dir:rename
→ {oldPath, newPath}
,oldPath
being the current directory path, and newPath
the desired new path.dir:move
→ {oldPath, newPath}
,oldPath
being the current directory path, and newPath
the desired new path.newPath
.dir:delete
→ {path}
,path
representing the full path of the directory in question.confirm()
dialog for the user.The following events will be emitted when certain errors occur. All errors have an event detail object that is the same as for the non-error event, with an additional error
property that has a string value reflecting what went wrong.
dir:create:error
,dir:rename:error
,dir:move:error
,There are three functions supported by <file-tree>
:
.setFiles(paths)
,paths
being an array of strings, where each string represents a relative path that uses /
as path delimiter..select(path)
,.unselect()
,File tree tags may specify a "remove-empty" attribute, i.e.
<file-tree remove-empty="true"></file-tree>
Setting this attribute tells the file tree that it may delete directories that become empty due to file move/delete operations.
By default, file trees content "normally", even though under the hood all content is wrapped by a directory entry with path "." to act as a root. File tree tags may specify a "show-top-level" attribute to show this root directory, i.e.
<file-tree show-top-level="true"></file-tree>
If you wish to associate data with <file-entry>
and <dir-entry>
elements, you can do so by adding data to their .state
property either directly, or by using the .setState(update)
function, which takes an update object and applies all key:value pairs in the update to the element's state.
While in HTML context this should be obvious: this is done synchronously, unlike the similarly named function that you might be familiar with from frameworks like React or Preact. The <file-tree>
is a normal HTML element and updates take effect immediately.
If you don't like the default styling, just override it! This custom element uses normal CSS, so you're under no obligation to load the file-tree.css
file, either load it and then override the parts you want to customize, or don't even load file-tree.css
at all and come up with your own styling.
That said, there are a number of CSS variables that you override on the file-tree
selector if you just want to tweak things a little, with their current definitions being:
file-tree {
--fallback-icon: "🌲";
--open-dir-icon: "📒";
--closed-dir-icon: "📕";
--file-icon: "📄";
--dir-touch-padding: 0;
--open-dir-icon-cursor: pointer;
--closed-dir-icon-cursor: pointer;
--dir-heading-cursor: pointer;
--file-icon-cursor: pointer;
--file-heading-cursor: pointer;
--icon-size: 1.25em;
--line-height: 1.5em;
--indent: 1em;
--entry-padding: 0.25em;
--highlight-background: lightcyan;
--highlight-border-color: blue;
--drop-target-color: rgb(205, 255, 242);
}
For example, if you just want to customize the icons and colors, load the file-tree.css
and then load your own overrides that set new values for those CSS variables. Nice and simple!
<file-tree>
should work, start a discussion over on: https://github.com/Pomax/custom-file-tree/discussions— Pomax
v3.3.0 (July 23, 2024)
.unselect()
to force a highlight reset.FAQs
Add the custom element to your page context using plain old HTML:
The npm package custom-file-tree receives a total of 16 weekly downloads. As such, custom-file-tree popularity was classified as not popular.
We found that custom-file-tree demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.