Bookmark Manager JavaScript, PHP

👤 Sharing: AI
```javascript
// JavaScript Bookmark Manager (Client-side)

class BookmarkManager {
  constructor(containerId) {
    this.containerId = containerId;
    this.bookmarks = []; // Array to store bookmark objects (e.g., {title: "Google", url: "https://www.google.com"})
    this.loadBookmarks();  // Load bookmarks from localStorage on initialization
    this.renderBookmarks();
  }

  loadBookmarks() {
    try {
      const storedBookmarks = localStorage.getItem('bookmarks');
      if (storedBookmarks) {
        this.bookmarks = JSON.parse(storedBookmarks);
      }
    } catch (error) {
      console.error("Error loading bookmarks from localStorage:", error);
      this.bookmarks = []; // Reset to empty array on error.
    }
  }

  saveBookmarks() {
    try {
      localStorage.setItem('bookmarks', JSON.stringify(this.bookmarks));
    } catch (error) {
      console.error("Error saving bookmarks to localStorage:", error);
    }
  }

  addBookmark(title, url) {
    if (!title || !url) {
      alert("Title and URL are required!");
      return;
    }

    if (!this.isValidURL(url)) {
      alert("Invalid URL!");
      return;
    }


    const newBookmark = { title: title, url: url };
    this.bookmarks.push(newBookmark);
    this.saveBookmarks();
    this.renderBookmarks();
  }

  deleteBookmark(index) {
    if (index >= 0 && index < this.bookmarks.length) {
      this.bookmarks.splice(index, 1);
      this.saveBookmarks();
      this.renderBookmarks();
    }
  }


  isValidURL(url) {
        try {
            new URL(url);
            return true;
        } catch (_) {
            return false;
        }
  }

  renderBookmarks() {
    const container = document.getElementById(this.containerId);
    if (!container) {
      console.error(`Container element with ID '${this.containerId}' not found.`);
      return;
    }

    container.innerHTML = ''; // Clear existing content

    if (this.bookmarks.length === 0) {
      container.innerHTML = '<p>No bookmarks yet.</p>';
      return;
    }

    const list = document.createElement('ul');

    this.bookmarks.forEach((bookmark, index) => {
      const listItem = document.createElement('li');
      const link = document.createElement('a');
      link.href = bookmark.url;
      link.textContent = bookmark.title;
      link.target = "_blank"; // Open in a new tab/window

      const deleteButton = document.createElement('button');
      deleteButton.textContent = 'Delete';
      deleteButton.addEventListener('click', () => this.deleteBookmark(index));


      listItem.appendChild(link);
      listItem.appendChild(deleteButton);
      list.appendChild(listItem);
    });

    container.appendChild(list);
  }
}


// Example Usage (You'll need to add HTML elements with these IDs to your page)
document.addEventListener('DOMContentLoaded', () => {
  const bookmarkManager = new BookmarkManager('bookmarkList'); // 'bookmarkList' is the ID of the container element

  // Add event listener to the add bookmark form (assuming you have one)
  const addBookmarkForm = document.getElementById('addBookmarkForm');
  if (addBookmarkForm) {
    addBookmarkForm.addEventListener('submit', (event) => {
      event.preventDefault(); // Prevent form submission

      const titleInput = document.getElementById('bookmarkTitle');
      const urlInput = document.getElementById('bookmarkURL');

      if (titleInput && urlInput) {
        bookmarkManager.addBookmark(titleInput.value, urlInput.value);
        titleInput.value = ''; // Clear input fields
        urlInput.value = '';
      } else {
        console.error("Title or URL input field not found.");
      }
    });
  } else {
    console.warn("Add bookmark form not found. Ensure it has the ID 'addBookmarkForm'.");
  }
});
```

```php
<?php

// PHP Bookmark Manager (Server-side - Example using a file to store bookmarks)

class BookmarkManager {
    private $filePath;

    public function __construct($filePath = 'bookmarks.json') {
        $this->filePath = $filePath;
    }

    public function loadBookmarks() {
        if (file_exists($this->filePath)) {
            $json = file_get_contents($this->filePath);
            $bookmarks = json_decode($json, true); // Decode as an associative array

            if ($bookmarks === null && json_last_error() !== JSON_ERROR_NONE) {
                // Handle JSON decoding error
                error_log("JSON Decoding Error: " . json_last_error_msg());
                return []; // Return empty array to avoid further errors
            }

            return is_array($bookmarks) ? $bookmarks : [];  //Ensure we return array.
        } else {
            return [];
        }
    }

    public function saveBookmarks(array $bookmarks) {  // Type hint for $bookmarks
        $json = json_encode($bookmarks, JSON_PRETTY_PRINT); // Encode the array to JSON

        if ($json === false) {
            // Handle JSON encoding error
            error_log("JSON Encoding Error: " . json_last_error_msg());
            return false; // Indicate failure
        }

        if (file_put_contents($this->filePath, $json) === false) {
            // Handle file writing error
            error_log("Error writing to file: " . $this->filePath);
            return false; // Indicate failure
        }

        return true; // Indicate success
    }

    public function addBookmark($title, $url) {
        $bookmarks = $this->loadBookmarks();
        $bookmarks[] = ['title' => $title, 'url' => $url];
        return $this->saveBookmarks($bookmarks);
    }

    public function deleteBookmark($index) {
        $bookmarks = $this->loadBookmarks();
        if (isset($bookmarks[$index])) {
            unset($bookmarks[$index]);
            // Re-index the array to avoid gaps in numeric keys.  Important for JSON serialization!
            $bookmarks = array_values($bookmarks);  // Re-index numeric keys.
            return $this->saveBookmarks($bookmarks);
        }
        return false; // Indicate failure (bookmark not found)
    }


    public function isValidURL($url) {
        return filter_var($url, FILTER_VALIDATE_URL) !== false;
    }

    public function displayBookmarks() {
        $bookmarks = $this->loadBookmarks();

        if (empty($bookmarks)) {
            echo "<p>No bookmarks yet.</p>";
            return;
        }

        echo "<ul>";
        foreach ($bookmarks as $index => $bookmark) {
            $title = htmlspecialchars($bookmark['title']); // Escape for safety
            $url = htmlspecialchars($bookmark['url']);       // Escape for safety
            echo "<li><a href=\"$url\" target=\"_blank\">$title</a> ";
            echo "<form method='post' style='display: inline;'>"; // Inline form for delete button
            echo "<input type='hidden' name='action' value='delete'>";
            echo "<input type='hidden' name='index' value='$index'>";
            echo "<button type='submit'>Delete</button>";
            echo "</form>";
            echo "</li>";
        }
        echo "</ul>";
    }
}

// --- Usage Example (Inside a PHP page, e.g., index.php) ---

$bookmarkManager = new BookmarkManager('bookmarks.json');

// Handle form submissions
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    if (isset($_POST['action']) && $_POST['action'] == 'add') {
        $title = isset($_POST['title']) ? trim($_POST['title']) : '';
        $url = isset($_POST['url']) ? trim($_POST['url']) : '';

        if ($title && $url) {
            if ($bookmarkManager->isValidURL($url)) {
               $bookmarkManager->addBookmark($title, $url);
               // Redirect to prevent form resubmission on refresh
               header("Location: " . $_SERVER['PHP_SELF']);
               exit();

            } else {
                $error_message = "Invalid URL.";
            }
        } else {
            $error_message = "Title and URL are required.";
        }
    } elseif (isset($_POST['action']) && $_POST['action'] == 'delete') {
        $index = isset($_POST['index']) ? intval($_POST['index']) : -1; // Convert to integer
        if ($index >= 0) {
            $bookmarkManager->deleteBookmark($index);
            // Redirect to prevent form resubmission on refresh
            header("Location: " . $_SERVER['PHP_SELF']);
            exit();
        }
    }
}

?>

<!DOCTYPE html>
<html>
<head>
    <title>Bookmark Manager</title>
</head>
<body>

    <h1>Bookmark Manager</h1>

    <?php if (isset($error_message)): ?>
        <p style="color: red;"><?php echo htmlspecialchars($error_message); ?></p>
    <?php endif; ?>

    <form method="post">
        <input type="hidden" name="action" value="add">
        Title: <input type="text" name="title"><br>
        URL: <input type="text" name="url"><br>
        <button type="submit">Add Bookmark</button>
    </form>

    <h2>Bookmarks</h2>
    <?php $bookmarkManager->displayBookmarks(); ?>

</body>
</html>
```
👁️ Viewed: 19

Comments