/**
* @module bookmark-folder
*/
import Bookmark from "./bookmark.js"
/**
* @description
* A BookmarkFolder can hold references to link and folders
* @example
* import { BookmarkFolder } from "@thoughtsunificator/bookmarks-document"
*/
class BookmarkFolder extends Bookmark {
/**
* @static
* @type {str}
*/
static DEFAULT_TITLE = "New Folder"
/**
* @param {string} title
* @param {Date} createdAt - Valid ISO 8601 date string
* @param {Date} [updatedAt] - Valid ISO 8601 date string
* @param {boolean} root
*/
constructor(title, createdAt=null, updatedAt=null, root=false) {
super(title, Bookmark.FOLDER, createdAt, updatedAt)
/**
* Returns the children of this BookmarkFolder
* @type {Bookmark[]}
*/
this.children = []
/**
* Whether the BookmarkFolder is the root BookmarkFolder of the BookmarksDocument
*/
this.root = root
/**
* Whether the children are made visible
* Used to preserved the unfold state when moving a bookmark
*/
this.unfolded = false
}
/**
* Returns the children BookmarkFolder of this BookmarkFolder
* @type {BookmarkFolder[]}
*/
get childFolders() {
return this.children.filter(child => child.type === Bookmark.FOLDER)
}
/**
* @type {Bookmark}
*/
get firstBookmark() {
return this.children[0]
}
/**
* @type {BookmarkFolder}
*/
get firstBookmarkFolder() {
return this.childFolders[0]
}
/**
* @type {Bookmark}
*/
get lastBookmark() {
return this.children[this.children.length - 1]
}
/**
* @type {BookmarkFolder}
*/
get lastBookmarkFolder() {
const childFolders = this.childFolders
return childFolders[childFolders.length - 1]
}
get path() {
let path = ""
if(this.parent) {
path += this.parent.path
}
path += "/" + this.title
return path
}
/**
* @returns {BookmarkFolder}
* @param {boolean} deep
* @todo original property to access the original bookmark
*/
clone(deep) {
const bookmarkFolder = new BookmarkFolder(this.title, new Date())
bookmarkFolder.ownerDocument = this.ownerDocument
if(deep) {
for(const child of this.children) {
bookmarkFolder.appendChild(child.clone(true))
}
}
return bookmarkFolder
}
/**
* Add a child Bookmark to this BookmarkFolder
* @param {Bookmark} bookmark
*/
appendChild(bookmark) {
const titles = this.children.map(child => child.title)
if(titles.includes(bookmark.title)) {
throw new Error(`A bookmark with the title '${bookmark.title}' already exists`)
}
if(bookmark.parent !== null) {
bookmark.remove()
}
this.children.push(bookmark)
bookmark.parent = this
}
/**
* Remove a child Bookmark from this BookmarkFolder
* @param {Bookmark} bookmark
*/
removeChild(bookmark) {
this.children.splice(this.children.indexOf(bookmark), 1)
bookmark.parent = null
}
/**
* Whether a Bookmark is contained in the BookmarkFolder
* @returns {boolean}
* @todo move out
*/
contains(bookmark) {
const treeWalker = this.ownerDocument.createTreeWalker(this)
while (treeWalker.nextBookmark()) {
if(treeWalker.currentBookmark === bookmark) {
return true
}
}
return false
}
/**
*
* @param {Bookmark} newBookmark
* @param {Bookmark} referenceBookmark
*/
insertBefore(newBookmark, referenceBookmark) {
if(newBookmark.parent !== null) {
newBookmark.remove()
}
this.children.splice(this.children.indexOf(referenceBookmark), 0, newBookmark)
newBookmark.parent = this
}
/**
*
* @param {Bookmark} newBookmark
* @param {Bookmark} referenceBookmark
*/
insertAfter(newBookmark, referenceBookmark) {
if(newBookmark.parent !== null) {
newBookmark.remove()
}
this.children.splice(this.children.indexOf(referenceBookmark) + 1, 0, newBookmark)
newBookmark.parent = this
}
/**
* Return the serializable version of a BookmarkFolder (removing any unwanted properties)
* @returns {object}
*/
serialize() {
return {
type: "folder",
title: this.title,
createdAt: this.createdAt.toISOString(),
updatedAt: this.updatedAt?.toISOString() || null,
attributes: this.attributes,
children: this.children.map(child => child.serialize())
}
}
}
export default BookmarkFolder