tooltip, char bar
This commit is contained in:
parent
e32803b7f9
commit
95cee55d0c
BIN
database/auth.db
BIN
database/auth.db
Binary file not shown.
BIN
database/live.db
BIN
database/live.db
Binary file not shown.
98
docs/tooltip.md
Normal file
98
docs/tooltip.md
Normal file
|
@ -0,0 +1,98 @@
|
|||
# Tooltip
|
||||
|
||||
The tooltip library is Isotip, taken and modified by Sharkk! Here is the breakdown of the API.
|
||||
|
||||
Configuring a specific tooltip is done via data attributes on an element.
|
||||
|
||||
### **`data-tooltip-classname`**
|
||||
|
||||
If you'd like to add a classname to the root tooltip element, set it here.
|
||||
|
||||
### **`data-tooltip-content`**
|
||||
|
||||
This sets the main body content of the tooltip into a `<p>` tag by default with a class of `tooltip-content`. Content is interpreted as plain text by default. To insert html, set the data-tooltip-html attribute to true.
|
||||
|
||||
### **`data-tooltip-title`**
|
||||
|
||||
This sets the title of the tooltip into a `<p>` tag by default with a class of `tooltip-title`.
|
||||
|
||||
### **`data-tooltip-html`**
|
||||
|
||||
Setting this to true will force Isotip to try and interpret the content as HTML. If it fails, it will interpret the content as plain text.
|
||||
|
||||
### **`data-tooltip-placement`**
|
||||
|
||||
This sets the position of the tooltip. Options are `top`, `right`, `bottom`, and `left`. By default, `top` is used for all tooltips.
|
||||
|
||||
### **`data-tooltip-container`**
|
||||
|
||||
This sets the element that the tooltip will be prepended to. By default, this is the `<body>` element.
|
||||
|
||||
Alternatively, programattic creation and destruction of tooltips is available.
|
||||
|
||||
### **`data-tooltip-scrollContainer`**
|
||||
|
||||
This sets the element that will have a scroll event bound to it. If your tooltip is inside a scrolling element (`overflow:scroll`), you need to add this!.
|
||||
|
||||
### **`data-tooltip-autoclose`**
|
||||
|
||||
If set to false, the tooltip will *not* close unless you do so programmatically with `isotip.close()`. Normal tooltips will not open until the open one has been closed!
|
||||
|
||||
### **`init( config )`**
|
||||
|
||||
The init method provides automatic event binding for tooltips. It sets up delegated event listeners for `.tooltip-click`, `.tooltip-hover`, and `.tooltip-focus` for click, mouseover, and focus events respectively. You can pass in an optional config object to overwrite any of the default options.
|
||||
|
||||
```javascript
|
||||
var options = {
|
||||
html: false, // set to true to always interpret content as HTML
|
||||
placement: 'top', // default placement of tooltips
|
||||
container: 'body', // default containing element for the tooltip
|
||||
scrollContainer: '.scroll-container', // default container for scroll watching
|
||||
template: '<div class="tooltip" data-tooltip-target="tooltip"></div>', // default template for the tooltip shell
|
||||
removalDelay: 200, // default number of ms before the tooltip is removed
|
||||
tooltipOffset: 10, // default number of px the tooltip is offset from the trigger element
|
||||
windowPadding: { // window bounds for tooltip repositioning
|
||||
top: 10,
|
||||
right: 10,
|
||||
bottom: 10,
|
||||
left: 10
|
||||
}
|
||||
};
|
||||
|
||||
Tooltip.init( config );
|
||||
```
|
||||
|
||||
### **`open( trigger, config )`**
|
||||
|
||||
The open method will create the tooltip, insert it into the DOM, and position it in relation to it's trigger. The trigger can be an element or a CSS selector. The object to be passed in will serve as a replacement for the data attributes on the trigger.
|
||||
|
||||
```javascript
|
||||
var config = {
|
||||
className: 'specific-class', // set to add a class to the tooltip
|
||||
html: false, // set to true to interpret content as HTML
|
||||
placement: 'top', // where to place the tooltip in relation to the trigger
|
||||
content: 'Tooltip content', // the content to go into the tooltip,
|
||||
title: 'Tooltip title', // the text to go in the title, if any
|
||||
container: document.querySelector('.container'), // the container to append the tooltip to
|
||||
scrollContainer: document.querySelector('.scroll-container'), // the container to bind the scroll event to
|
||||
autoClose: false // set to false if you only want to close the tooltip programmatically. Normal tooltips won't open until the open one has been closed!
|
||||
};
|
||||
|
||||
Tooltip.open( '.tooltip', config );
|
||||
```
|
||||
|
||||
### **`close( tooltip )`**
|
||||
|
||||
The close method will remove a tooltip from the DOM. The tooltip to remove should be passed in and can be an element or a CSS selector.
|
||||
|
||||
```javascript
|
||||
Tooltip.close( '.tooltip' );
|
||||
```
|
||||
|
||||
### **`positionTooltip( tooltip, trigger, placement )`**
|
||||
|
||||
The positionTooltip method will re-evaluate the position of a tooltip in relation to it's trigger element. Only the tooltip and trigger need to be passed in, and placement will default to what's been configured by `init()`. Tooltip and trigger can be either an element or a CSS selector.
|
||||
|
||||
```javascript
|
||||
Tooltip.positionTooltip( '.tooltip', '.tooltip-click', 'left' );
|
||||
```
|
|
@ -25,12 +25,11 @@ body {
|
|||
border: none;
|
||||
font-size: 1rem;
|
||||
background: #f7f8fa linear-gradient(rgba(255, 255, 255, 0), rgba(0, 0, 0, 0.1));
|
||||
box-shadow: 0 1px 0 1px rgba(255, 255, 255, 0.3) inset, 0 0 0 1px #adb2bb inset;
|
||||
color: #111111;
|
||||
margin: 0rem 0.25rem 0rem 0rem;
|
||||
padding: 0.5rem 1rem 0.5rem;
|
||||
text-align: center;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 1px 0 1px rgba(255, 255, 255, 0.3) inset, 0 0 0 1px #adb2bb inset;
|
||||
user-select: none;
|
||||
text-decoration: none;
|
||||
transition: opacity 0.1s ease, background-color 0.1s ease, color 0.1s ease, background 0.1s ease;
|
||||
|
@ -43,6 +42,11 @@ body {
|
|||
color: rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
|
||||
&.badge {
|
||||
font-size: 10px;
|
||||
padding: 0.1rem 0.25rem;
|
||||
}
|
||||
|
||||
&.primary {
|
||||
background-color: #f4cc67;
|
||||
background-image: linear-gradient(rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.1));
|
||||
|
@ -98,6 +102,31 @@ header {
|
|||
|
||||
main {
|
||||
padding: 1rem;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 8fr 1fr;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
aside#left {
|
||||
.box {
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
border-radius: 0.15rem;
|
||||
|
||||
&#nav > a {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 0.15rem;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
transition: color, background-color 0.2s ease;
|
||||
|
||||
&:hover, &.active {
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
footer {
|
||||
|
@ -116,11 +145,11 @@ footer {
|
|||
|
||||
#char-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 1rem;
|
||||
height: 34px;
|
||||
color: white;
|
||||
gap: 1rem;
|
||||
background-image: url('/assets/img/deco-bar2.jpg');
|
||||
|
||||
& > div {
|
||||
|
@ -172,3 +201,60 @@ span.badge {
|
|||
width: 960px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.char-meter {
|
||||
background-color: black;
|
||||
height: 16px;
|
||||
min-width: 100px;
|
||||
border-radius: 0.1rem;
|
||||
position: relative;
|
||||
|
||||
& > div {
|
||||
height: 100%;
|
||||
border-radius: 0.1rem;
|
||||
overflow: hidden;
|
||||
|
||||
&.hp {
|
||||
background-color: #e57373;
|
||||
background-image: linear-gradient(rgba(255, 255, 255, 0.15), rgba(139, 0, 0, 0.1));
|
||||
box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset;
|
||||
border: 1px solid;
|
||||
border-color: #d32f2f #c62828 #b71c1c;
|
||||
}
|
||||
|
||||
&.mp {
|
||||
background-color: #5a9bd4;
|
||||
background-image: linear-gradient(rgba(255, 255, 255, 0.15), rgba(60, 100, 150, 0.1));
|
||||
box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset;
|
||||
border: 1px solid;
|
||||
border-color: #4a8ab0 #3a7a9c #2a6a88;
|
||||
}
|
||||
|
||||
&.tp {
|
||||
background-color: #f4cc67;
|
||||
background-image: linear-gradient(rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.1));
|
||||
box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset;
|
||||
border: 1px solid;
|
||||
border-color: #C59F43 #AA8326 #957321;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
background-color: black;
|
||||
color: white;
|
||||
border: 1px solid #666;
|
||||
font-size: 14px;
|
||||
padding: 0.5rem;
|
||||
box-shadow: 0 0 0.5rem 0.1rem rgba(0, 0, 0, 0.2);
|
||||
border-radius: 0.1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tooltip-trigger {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
|
3
public/assets/scripts/tooltip.js
Normal file
3
public/assets/scripts/tooltip.js
Normal file
File diff suppressed because one or more lines are too long
10
public/assets/scripts/tooltip.js.map
Normal file
10
public/assets/scripts/tooltip.js.map
Normal file
File diff suppressed because one or more lines are too long
|
@ -13,7 +13,7 @@ $r = [];
|
|||
*/
|
||||
router_get($r, '/', function () {
|
||||
if (user()) must_have_character();
|
||||
echo render('layouts/basic', ['view' => 'pages/home']);
|
||||
echo render('layouts/basic', ['view' => 'pages/home', 'activeTab' => nav_tabs['home']]);
|
||||
});
|
||||
|
||||
/*
|
||||
|
@ -28,6 +28,7 @@ router_post($r, '/auth/logout', 'auth_controller_logout_post');
|
|||
/*
|
||||
Characters
|
||||
*/
|
||||
router_get($r, '/characters', 'char_controller_select_get');
|
||||
router_post($r, '/character/create', 'char_controller_create_post');
|
||||
router_post($r, '/character/select', 'auth_controller_change_character_post');
|
||||
router_get($r, '/character/create-first', 'char_controller_create_first_get');
|
||||
|
|
15
src/auth.php
15
src/auth.php
|
@ -61,13 +61,9 @@ function guest_only(): void
|
|||
*/
|
||||
function must_have_character(): void
|
||||
{
|
||||
// If there is a character selected, and the data exists, return early.
|
||||
if ($_SESSION['user']['char_id'] !== 0 && !empty($_SESSION['char'])) return;
|
||||
|
||||
// If there is a character selected, make sure the session is up to date.
|
||||
if ($_SESSION['user']['char_id'] !== 0 && empty($_SESSION['char'])) {
|
||||
$char = db_query(db_live(), 'SELECT * FROM characters WHERE id = :c', [':c' => $_SESSION['user']['char_id']]);
|
||||
$char = $char = $char->fetchArray(SQLITE3_ASSOC);
|
||||
if ($_SESSION['user']['char_id'] !== 0) {
|
||||
$char = db_query(db_live(), 'SELECT * FROM characters WHERE id = :c', [':c' => $_SESSION['user']['char_id']])->fetchArray(SQLITE3_ASSOC);
|
||||
$_SESSION['char'] = $char;
|
||||
return;
|
||||
}
|
||||
|
@ -77,10 +73,7 @@ function must_have_character(): void
|
|||
|
||||
// if no character selected, select the first one
|
||||
if ($_SESSION['user']['char_id'] === 0) {
|
||||
$char = db_query(db_live(), 'SELECT * FROM characters WHERE user_id = :u ORDER BY id ASC LIMIT 1', [':u' => user('id')]);
|
||||
$char = $char->fetchArray(SQLITE3_ASSOC);
|
||||
$_SESSION['user']['char_id'] = $char['id'];
|
||||
db_query(db_auth(), 'UPDATE users SET char_id = :c WHERE id = :u', [':c' => $char['id'], ':u' => user('id')]);
|
||||
$_SESSION['char'] = $char;
|
||||
$char = db_query(db_live(), 'SELECT * FROM characters WHERE user_id = :u ORDER BY id ASC LIMIT 1', [':u' => user('id')])->fetchArray(SQLITE3_ASSOC);
|
||||
change_user_character($char['id']);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
<?php
|
||||
|
||||
const nav_tabs = [
|
||||
'home' => 0,
|
||||
'chars' => 1,
|
||||
];
|
||||
|
||||
/**
|
||||
* Render the logout button's form.
|
||||
*/
|
||||
|
@ -17,3 +22,11 @@ function c_char_bar(): string
|
|||
if (!char()) return '';
|
||||
return render('components/char_bar', ['char' => char()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the left sidebar navigation menu. Provide the active tab to highlight it.
|
||||
*/
|
||||
function c_left_nav(int $activeTab): string
|
||||
{
|
||||
return render('components/left_nav', ['activeTab' => $activeTab]);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,18 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Display a list of characters for the currently logged in user.
|
||||
*/
|
||||
function char_controller_select_get(): void
|
||||
{
|
||||
auth_only();
|
||||
must_have_character();
|
||||
|
||||
$chars = char_list(user('id'));
|
||||
|
||||
echo render('layouts/basic', ['view' => 'pages/chars/select', 'chars' => $chars, 'activeTab' => nav_tabs['chars']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Form to create your first character.
|
||||
*/
|
||||
|
@ -10,7 +23,7 @@ function char_controller_create_first_get(): void
|
|||
// If the user already has a character, redirect them to the main page.
|
||||
if (char_count(user('id')) > 0) redirect('/');
|
||||
|
||||
echo render('layouts/basic', ['view' => 'pages/chars/first']);
|
||||
echo render('layouts/basic', ['view' => 'pages/chars/first', 'activeTab' => nav_tabs['chars']]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -147,3 +147,13 @@ function change_user_character(int $char_id): void
|
|||
db_query(db_auth(), "UPDATE users SET char_id = :c WHERE id = :u", [':c' => $char_id, ':u' => user('id')]);
|
||||
$_SESSION['char'] = char_find($char_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a percent between two ints, rounded to the nearest whole number or return 0.
|
||||
*/
|
||||
function percent(int $num, int $denom, int $precision = 4): int
|
||||
{
|
||||
if ($denom === 0) return 0;
|
||||
$p = ($num / $denom) * 100;
|
||||
return $p < 0 ? 0 : round($p, $precision);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,30 @@
|
|||
<div id="char-bar">
|
||||
<div>
|
||||
<img class="icon" src="/assets/img/icons/user1.png" alt="User">
|
||||
<?= $char['name'] ?> <span class="badge ml-2"><?= $char['level'] ?></span>
|
||||
<?= $char['name'] ?> <span class="badge ml-2 tooltip-hover" data-tooltip-content="Level"><?= $char['level'] ?></span>
|
||||
<?php if ($char['attrib_points'] > 0): ?>
|
||||
<span class="ui button primary badge ml-2 tooltip-hover" data-tooltip-content="Attribute Points"><?= $char['attrib_points'] ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="char-meter">
|
||||
<div class="hp" style="width: <?= percent($char['current_hp'], $char['max_hp']) ?>%"></div>
|
||||
<div class="tooltip-trigger tooltip-hover" data-tooltip-content="Health<br><?= $char['current_hp'] ?> / <?= $char['max_hp'] ?>"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="char-meter">
|
||||
<div class="mp" style="width: <?= percent($char['current_mp'], $char['max_mp']) ?>%"></div>
|
||||
<div class="tooltip-trigger tooltip-hover" data-tooltip-content="Mana<br><?= $char['current_mp'] ?> / <?= $char['max_mp'] ?>"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="char-meter">
|
||||
<div class="tp" style="width: <?= percent($char['current_tp'], $char['max_tp']) ?>%"></div>
|
||||
<div class="tooltip-trigger tooltip-hover" data-tooltip-content="Travel Points<br><?= $char['current_tp'] ?> / <?= $char['max_tp'] ?>"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
4
templates/components/left_nav.php
Normal file
4
templates/components/left_nav.php
Normal file
|
@ -0,0 +1,4 @@
|
|||
<div id="nav" class="box">
|
||||
<a href="/" class="<?= $activeTab === 0 ? 'active' : '' ?>">Home</a>
|
||||
<a href="/characters" class="<?= $activeTab === 1 ? 'active' : '' ?>">Characters</a>
|
||||
</div>
|
0
templates/components/right_nav.php
Normal file
0
templates/components/right_nav.php
Normal file
|
@ -19,14 +19,28 @@
|
|||
<?php else: ?>
|
||||
<a class="ui button primary" href="/auth/login">Login</a>
|
||||
<a class="ui button secondary" href="/auth/register">Register</a>
|
||||
<?php endif ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<?= c_char_bar(user('char_id')) ?>
|
||||
|
||||
<main>
|
||||
<aside id="left">
|
||||
<?php if (user()): ?>
|
||||
<?= c_left_nav($activeTab ?? 0) ?>
|
||||
<?php endif; ?>
|
||||
</aside>
|
||||
|
||||
<div id="center">
|
||||
<?= render($view, $data) ?>
|
||||
</div>
|
||||
|
||||
<aside id="right">
|
||||
<?php if (user()): ?>
|
||||
// right nav
|
||||
<?php endif; ?>
|
||||
</aside>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
|
@ -34,5 +48,10 @@
|
|||
<p>q<?= $GLOBALS['queries'] ?></p>
|
||||
<p>v<?= env('version') ?></p>
|
||||
</footer>
|
||||
|
||||
<script type="module">
|
||||
import Tooltip from '/assets/scripts/tooltip.js';
|
||||
Tooltip.init();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
16
templates/pages/chars/select.php
Normal file
16
templates/pages/chars/select.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<h1>Characters</h1>
|
||||
<?php
|
||||
$list = char_list(user('id'));
|
||||
if (count($list) > 0): ?>
|
||||
<form action="/character/select" method="post">
|
||||
<input type="hidden" name="csrf" value="<?= csrf() ?>">
|
||||
<?php foreach ($list as $id => $char): ?>
|
||||
<input type="radio" name="char_id" value="<?= $id ?>" id="char_<?= $id ?>">
|
||||
<label for="char_<?= $id ?>"><?= $char['name'] ?> (Level <?= $char['level'] ?>)</label><br>
|
||||
<?php endforeach; ?>
|
||||
<input type="submit" value="Select Character">
|
||||
</form>
|
||||
<?php else: ?>
|
||||
<!-- Should never see this particular message. If you have, there's a bug. -->
|
||||
<p>You have no characters.</p>
|
||||
<?php endif; ?>
|
|
@ -1,21 +1,8 @@
|
|||
<?php if (!user()): ?>
|
||||
<h2>Welcome!</h2>
|
||||
<h1>Welcome!</h1>
|
||||
<a href="/auth/login" class="ui button primary">Login</a>
|
||||
<a href="/auth/register" class="ui button secondary">Register</a>
|
||||
<?php else: ?>
|
||||
<?php if (char_count(user('id')) > 0): ?>
|
||||
<h3>Characters</h3>
|
||||
<form action="/character/select" method="post">
|
||||
<input type="hidden" name="csrf" value="<?= csrf() ?>">
|
||||
<?php foreach (char_list(user('id')) as $id => $char): ?>
|
||||
<input type="radio" name="char_id" value="<?= $id ?>" id="char_<?= $id ?>">
|
||||
<label for="char_<?= $id ?>"><?= $char['name'] ?> (Level <?= $char['level'] ?>)</label><br>
|
||||
<?php endforeach; ?>
|
||||
<input type="submit" value="Select Character">
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<form action="/character/create" method="post">
|
||||
<input type="hidden" name="csrf" value="<?= csrf() ?>">
|
||||
<input type="text" name="name" placeholder="Character Name">
|
||||
<input type="submit" value="Create Character">
|
||||
</form>
|
||||
<h1 class="tooltip-click" data-tooltip-content="Hover-based tooltip">Home</h1>
|
||||
<?= print_r(char()) ?>
|
||||
<?php endif; ?>
|
||||
|
|
Loading…
Reference in New Issue
Block a user