Skip to content

Commit

Permalink
add infinite scrolling
Browse files Browse the repository at this point in the history
  • Loading branch information
sebcode committed Jul 19, 2017
1 parent 838111b commit eef8d09
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 41 deletions.
24 changes: 17 additions & 7 deletions BookmarkManager.php
Expand Up @@ -6,6 +6,7 @@

class BookmarkManager
{
protected $config;
protected $db;
protected $user;
protected $baseDir;
Expand All @@ -14,13 +15,13 @@ class BookmarkManager

public function __construct($requestUri = '/')
{
$config = require __DIR__.'/config.php';
$this->config = require __DIR__.'/config.php';

if (empty($config['baseDir'])) {
if (empty($this->config['baseDir'])) {
throw new \Exception('baseDir not defined in config.php');
}

$this->baseDir = $config['baseDir'];
$this->baseDir = $this->config['baseDir'];

if (!is_dir($this->baseDir)) {
throw new \Exception('invalid baseDir in config.php');
Expand All @@ -32,11 +33,11 @@ public function __construct($requestUri = '/')

$this->baseDir = rtrim($this->baseDir, '/').'/';

if (empty($config['baseUri'])) {
if (empty($this->config['baseUri'])) {
throw new \Exception('baseUri not defined in config.php');
}

$baseUri = rtrim($config['baseUri'], '/').'/';
$baseUri = rtrim($this->config['baseUri'], '/').'/';

if (strpos($requestUri, $baseUri) !== 0) {
throw new \Exception('invalid baseuri');
Expand Down Expand Up @@ -75,6 +76,15 @@ public function __construct($requestUri = '/')
$this->db = new DB($this->baseDir.$user.'/b.db');
}

public function getConfig($key)
{
if (isset($this->config[$key])) {
return $this->config[$key];
}

return false;
}

public function getDB()
{
return $this->db;
Expand Down Expand Up @@ -145,8 +155,8 @@ public function handleAjaxRequest($postData)
$result['result'] = true;
}

header('Content-Type: application/json');
echo json_encode($result, JSON_FORCE_OBJECT);
header('Content-Type: application/json; charset=utf-8');
echo json_encode($result, JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE);

exit();
}
Expand Down
22 changes: 18 additions & 4 deletions DB.php
Expand Up @@ -55,19 +55,33 @@ public function exists($link)
return (bool) $st->fetch();
}

public function getEntries($filter = false)
public function getEntries($filter = false, $skip = false, $count = false)
{
if (!$filter) {
$filter = '%';
}

$st = $this->pdo->prepare('
if ($skip !== false && $count !== false) {
$limit = 'LIMIT :skip, :count';
} else {
$limit = '';
}

$st = $this->pdo->prepare("
SELECT id, desc, link FROM b
WHERE desc LIKE :filter
ORDER BY date DESC
');
$limit
");

$args = [ ':filter' => "%$filter%" ];

if ($skip !== false && $count !== false) {
$args['skip'] = $skip;
$args['count'] = $count;
}

$st->execute([ ':filter' => "%$filter%" ]);
$st->execute($args);

$ret = $st->fetchAll();

Expand Down
2 changes: 1 addition & 1 deletion LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2011-2016 Sebastian Volland
Copyright (c) 2011-2017 Sebastian Volland

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
72 changes: 55 additions & 17 deletions README.md
@@ -1,6 +1,14 @@
# b - Bookmark manager

b is a minimalistic bookmark manager for your own server written in PHP where bookmarks are stored in a sqlite database.
b is a minimalistic bookmark manager for your own server. Written in PHP.
Bookmarks are stored in a sqlite database. Features:

* filtering
* tagging
* automatic fetching of page title
* infinite scrolling (optional)
* bookmarklet
* multiple users

### Requirements

Expand All @@ -10,15 +18,23 @@ b is a minimalistic bookmark manager for your own server written in PHP where bo

### Configuration instructions

* Copy all repository files to a directory accessible by the webserver-user, like `/var/www/b`
* Copy all repository files to a directory accessible by the webserver-user,
like `/var/www/b`
* Move `config.template.php` to `config.php` and edit it
* `baseDir` is the directory where the sqlite dbs are stored, e.g. `/var/bookmarks/`. The directory must be readable and writeable by the webserver-user
* `baseUri` is the base uri's relative path param, e.g. `/b/` if the website is accessible via `http://example.com/b/`. Or use `/` for `http://bookmarks.example.com/` for example, if you want to have a dedicated subdomain for the service.
* Create a new user-account simply by creating a new directory in `baseDir`: `mkdir /var/bookmarks/peter/`
* `baseDir` is the directory where the sqlite dbs are stored, e.g.
`/var/bookmarks/`. The directory must be readable and writeable by the
webserver-user
* `baseUri` is the base uri's relative path param, e.g. `/b/` if the website
is accessible via `http://example.com/b/`. Or use `/` for
`http://bookmarks.example.com/` for example, if you want to have a
dedicated subdomain for the service.
* Create a new user-account simply by creating a new directory in `baseDir`:
`mkdir /var/bookmarks/peter/`

#### Webserver configuration example for apache

* If you want your bookmarks to be accessible under their own subdomain like `http://bookmarks.example.com/`, add a virtual host to your `httpd.conf`:
* If you want your bookmarks to be accessible under their own subdomain like
`http://bookmarks.example.com/`, add a virtual host to your `httpd.conf`:

<VirtualHost *:80>
ServerName bookmarks.example.com
Expand All @@ -39,32 +55,54 @@ b is a minimalistic bookmark manager for your own server written in PHP where bo
</Directory>
</VirtualHost>

* Create a password file and restart apache. If you don't want to use a password, remove the "Password protection" part from the virtual host configuration.
* Create a password file and restart apache. If you don't want to use a
password, remove the "Password protection" part from the virtual host
configuration.

htpasswd -c /opt/bookmarks/htusers peter
apachectl restart

* If you want to use a localhost fake domain, add the host to your `/etc/hosts` file:
* If you want to use a localhost fake domain, add the host to your
`/etc/hosts` file:

127.0.0.1 bookmarks.example.com

* Peter's bookmarks should now be accessible via `http://bookmarks.example.com/peter`
* Run a configuration-check via `http://bookmarks.example.com/index.php?configtest`
* Peter's bookmarks should now be accessible via
`http://bookmarks.example.com/peter`
* Run a configuration-check via
`http://bookmarks.example.com/index.php?configtest`

### How to use

* To add a new bookmark, simply paste it into the input field and press return. the url may be followed by hash tags, e.g. `http://example.com #example #bla #wurst`
* The website's title is automatically fetched and the bookmark is added to the database.
* Edit title by double clicking it. This opens a prompt-dialog where you can edit the title. Enter '-' (minus sign) to remove an entry.
* To add a new bookmark, simply paste it into the input field and press
return. the url may be followed by hash tags, e.g. `http://example.com
#example #bla #wurst`
* The website's title is automatically fetched and the bookmark is added to
the database.
* Edit title by double clicking it. This opens a prompt-dialog where you can
edit the title. Enter '-' (minus sign) to remove an entry.
* To edit the URL, double click beside the link.
* The input field can also be used to filter bookmarks. Filtering is done with a full-text search on all titles.
* The input field can also be used to filter bookmarks. Filtering is done with
a full-text search on all titles.

### Infinite scrolling

If you have a massive amount of bookmarks and you don't want to load them all at
once, you can activate infinite scrolling. This will load a limited amount on
bookmarks initially and load more when you scroll to the bottom of the page.
Activate infinite scrolling by adding `'infiniteScrolling' => 200` to your
`config.php`. Replace `200` with the number of bookmarks you want to load each
time you hit the bottom.

### Bookmarklet

Visit `/[user]/bookmarklet` to access the user's bookmarklet, e.g. `http://bookmarks.example.com/peter/bookmarklet`. (Thanks to nibreh for the suggestion!)
Visit `/[user]/bookmarklet` to access the user's bookmarklet, e.g.
`http://bookmarks.example.com/peter/bookmarklet`. (Thanks to nibreh for the
suggestion!)

### Credits

Copyright (c) 2011-2016 Sebastian Volland http://github.com/sebcode
Copyright (c) 2011-2017 Sebastian Volland http://github.com/sebcode

The source code is licensed under the terms of the MIT license (see LICENSE file).
The source code is licensed under the terms of the MIT license (see LICENSE
file).
37 changes: 37 additions & 0 deletions bookmarkManager.js
Expand Up @@ -147,6 +147,43 @@

return false
})

let loadingMore = false
let ifStep = window.infiniteScrolling
let ifSkip = ifStep

async function loadMore() {
if (loadingMore) {
return
}

loadingMore = true

const url =
`?filter=${encodeURIComponent(window.filter)}` +
`&format=html&count=${ifStep}&skip=${ifSkip}`
const res = await fetch(url)
const text = await res.text()

if (!text) {
return
}

contentEl.insertAdjacentHTML('beforeend', text)
ifSkip += ifStep
loadingMore = false
}

if (window.infiniteScrolling) {
window.addEventListener('scroll', e => {
const offset =
document.body.offsetHeight - (window.pageYOffset + window.innerHeight)

if (offset < 500) {
loadMore()
}
})
}
})()

// vim: et ts=2 sw=2 sts=2
5 changes: 4 additions & 1 deletion config.template.php
Expand Up @@ -2,5 +2,8 @@

return [
'baseDir' => '/opt/bookmarks/',
'baseUri' => '/'
'baseUri' => '/',
/* Optional: Infinite scrolling. Value is the number of items to load
* on each increment. */
//'infiniteScrolling' => 200,
];
67 changes: 56 additions & 11 deletions index.php
Expand Up @@ -50,18 +50,64 @@
$filter = false;
}

$entries = $b->getDB()->getEntries($filter);
$skip = false;
$count = $b->getConfig('infiniteScrolling');
if ($count !== false) {
$skip = 0;
}

if (isset($_GET['skip'])) {
$skip = $_GET['skip'];
}

if (isset($_GET['count'])) {
$count = $_GET['count'];
}

if (!empty($_GET['format'])) {
$format = $_GET['format'];
} else {
$format = false;
}

$entries = $b->getDB()->getEntries($filter, $skip, $count);

if ($format === 'json') {
header('Content-Type: application/json; charset=utf-8');
echo json_encode($entries, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
exit();
}

if ($format === 'html') {
dumpEntries($entries);
exit();
}
} catch (\Exception $e) {
if ($e->getCode()) {
http_response_code($e->getCode());
if (($code = $e->getCode()) && is_numeric($code)) {
http_response_code($code);
} else {
http_response_code(500);
}

echo $e->getMessage();
throw $e;
exit();
}

function dumpEntries($entries)
{
foreach ($entries as $entry) {
?>
<div class="entry" id="entry_<?php echo $entry['id']; ?>" data-id="<?php echo $entry['id']; ?>" data-title="<?php echo htmlspecialchars($entry['desc']); ?>">
<div class="title"><?php echo BookmarkManager::formatDesc($entry['desc'], false); ?></div>
<a class="link" target="_blank" href="<?php echo htmlspecialchars($entry['link']); ?>"><?php echo htmlspecialchars($entry['link']); ?></a>
<div class="tags"><?php echo BookmarkManager::formatTags($entry['desc']); ?></div>
</div>

<?php
}
}

?>
<!DOCTYPE html>
<html>
Expand All @@ -85,18 +131,17 @@
</form>
</div>

<?php foreach ($entries as $entry): ?>
<?php dumpEntries($entries); ?>

<div class="entry" id="entry_<?php echo $entry['id']; ?>" data-id="<?php echo $entry['id']; ?>" data-title="<?php echo htmlspecialchars($entry['desc']); ?>">
<div class="title"><?php echo BookmarkManager::formatDesc($entry['desc'], false); ?></div>
<a class="link" target="_blank" href="<?php echo htmlspecialchars($entry['link']); ?>"><?php echo htmlspecialchars($entry['link']); ?></a>
<div class="tags"><?php echo BookmarkManager::formatTags($entry['desc']); ?></div>
</div>

<?php endforeach; ?>

</div>
<script>
window.filter = <?php echo $filter ? json_encode($filter) : "''"; ?>

<?php if ($step = $b->getConfig('infiniteScrolling')): ?>
window.infiniteScrolling = <?php echo $step; ?>
<?php endif; ?>
</script>
<script src="bookmarkManager.js"></script>

<?php if (!empty($_GET['add'])): ?>
Expand Down

0 comments on commit eef8d09

Please sign in to comment.