Skip to content

Commit

Permalink
Fix usage typo and add toggle buttons for details1
Browse files Browse the repository at this point in the history
  • Loading branch information
nuxodin committed Feb 22, 2024
1 parent e14063c commit c01defb
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 36 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# [u1-navigable] - attribute
Make elements navigatable

## Ussage
## Usage

```html
<a href="#navigable">open dialog</a>
Expand Down
12 changes: 8 additions & 4 deletions TargetObserver.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
// checks for hashchange and element matches

const observers = new Set();

export class TargetObserver {

/**
* @param {Object} opts
* @param {Function} opts.on - called when a element is the target
* @param {Function} opts.off - called when a element lost the target
* @param {Function} opts.in - called when a element or a descendant is the target
* @param {Function} opts.out - called when a element and non of its descendants is the target
* @param {Function} opts.out - called when a element lost the target including descendants
* @param {String} opts.matches - CSS selector for elements we listen to
*/
constructor(opts) {
Expand Down Expand Up @@ -65,8 +69,8 @@ export class TargetObserver {
let active = null;

function checkTarget(e) {
const target = (location.hash && document.querySelector(location.hash)) || false;
const changed = e ? e.oldURL !== e.newURL : target !== active; // test url vs old url bacause it can have lost a trigger when changed using replaceState
const target = location.hash ? document.getElementById(location.hash.substring(1)) : false;
const changed = e ? e.oldURL !== e.newURL : target !== active; // test url vs old-url because it can have lost a trigger when changed using replaceState
if (!changed) return;
for (const observer of observers) {
observer._testOff(active);
Expand All @@ -78,7 +82,7 @@ checkTarget();
addEventListener('hashchange', checkTarget);


// ussage:
// Usage:
// const observer = new TargetObserver({
// in: (target) => console.log(target),
// out: (target) => console.log(target),
Expand Down
25 changes: 13 additions & 12 deletions U1TargetObserver.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// checks for the "u1-target" query parameter and calls the on/off functions
// e.g. ?u1-target=details1+checkbox3+dialog1

const observers = new Set();

export class U1TargetObserver {
Expand Down Expand Up @@ -32,10 +35,10 @@ let actives = new Set();

function checkTargets(){
const newest = new Set();
const param = new URL(window.location).searchParams.get('u1-target');
const param = new URL(location).searchParams.get('u1-target');
if (param) {
for (const item of param.split(' ')) {
const el = document.getElementById(item);
const el = item && document.getElementById(item);
el && newest.add(el);
}
}
Expand All @@ -60,15 +63,13 @@ checkTargets();

// togglelParam
export function toggleParam(id, force, replace){
const url = new URL(window.location);
const url = new URL(location);
const targets = new Set((url.searchParams.get('u1-target')||'').split(' '));
const size = targets.size;
if (force===true) targets.add(id);
if (force===false) targets.delete(id);
if (targets.size!==size) { // changed
url.searchParams.set('u1-target', [...targets].join(' '));
history[replace?'replaceState':'pushState'](null, '', url.href);
// history.pushState({}, '', url+'');
checkTargets();
}
const isPresent = targets.has(id);
const shouldAdd = force ?? !isPresent;
if (shouldAdd === isPresent) return;
shouldAdd ? targets.add(id) : targets.delete(id);
url.searchParams.set('u1-target', [...targets].join(' '));
history[replace?'replaceState':'pushState'](null, '', url.href);
checkTargets();
}
44 changes: 35 additions & 9 deletions navigable.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// todo security check, is querySelector harmfull for user-input?

import {TargetObserver} from './TargetObserver.js';
import {U1TargetObserver, toggleParam} from './U1TargetObserver.js';

Expand All @@ -8,11 +6,9 @@ import {U1TargetObserver, toggleParam} from './U1TargetObserver.js';
new TargetObserver({
on: (el) => {
toggleParam(el.id, true, true);
const url = new URL(window.location);
const url = new URL(location);
url.hash = '';
window.history.replaceState(null, '', url.href);
},
off: (el) => {
history.replaceState(null, '', url.href);
},
matches: '[u1-navigable]'
})
Expand Down Expand Up @@ -45,20 +41,50 @@ addEventListener('toggle',e=>{
},true);


/* checkbox */
/* checkbox and radio */
new U1TargetObserver({
on: el => el.checked = true,
off: el => el.checked = false,
matches: 'input[type=checkbox][u1-navigable]',
matches: 'input:is([type=checkbox],[type=radio])[u1-navigable]',
});
addEventListener('change',e=>{
const el = e.target;
if (!el.matches('input[type=checkbox][u1-navigable][id]')) return;
if (!el.matches('input:is([type=checkbox],[type=radio])[u1-navigable][id]')) return;

if (el.type === 'radio') {
const elements = el.form ? el.form.elements[el.name] : document.getElementsByName(el.name);
elements.forEach(e => toggleParam(e.id, false)); // toggleParam(e.id, false, TRUE) does not work as expected, why?
}

if (el.checked) toggleParam(el.id, true);
else toggleParam(el.id, false);
});


/* popover */
new U1TargetObserver({
on: el => el.showPopover(),
off: el => el.hidePopover(),
matches: '[popover][u1-navigable]',
});
addEventListener('toggle', e => {
const el = e.target;
if (!el.matches('[popover][u1-navigable][id]')) return;
const newState = e.newState;
toggleParam(el.id, newState === 'open');
}, true);



/* *
// todo: unified close button
addEventListener('click', e => {
const el = e.target;
if (!el.matches('[u1-navigable-close]')) return;
const id = el.getAttribute('u1-navigable-close') || el.closest('[u1-navigable]').id;
toggleParam(id, false);
}, true);
/* */

// beta
// u1 unified api
Expand Down
10 changes: 10 additions & 0 deletions tests/U1TargetObserver.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@
<link rel=stylesheet href="https://cdn.jsdelivr.net/gh/u1ui/classless.css/classless.min.css">
<link rel=stylesheet href="https://cdn.jsdelivr.net/gh/u1ui/classless.css/more.min.css">
<link rel=stylesheet href="https://cdn.jsdelivr.net/gh/u1ui/classless.css/simple.min.css">
<script type=module src="../../u1/tests/test-init.js"></script>

<body>

<section>
<h1>Details</h1>

<button onclick="toggleParam('details1', true)">open</button>
<button onclick="toggleParam('details1', false)">close</button>
<button onclick="toggleParam('details1', null)">toggle</button>
<button onclick="toggleParam('details1', null, true)">toggle, no browser-back-history</button>

<details u1-navigable id=details1>
<summary>summary 1</summary>
More rext
Expand All @@ -25,10 +31,14 @@ <h1>Details</h1>
More rext
</details>


</section>

<script type=module>

import {U1TargetObserver, toggleParam} from "../U1TargetObserver.js";
window.toggleParam = toggleParam;


new U1TargetObserver({
on: el => el.open = true,
Expand Down
29 changes: 19 additions & 10 deletions tests/test.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<link rel=stylesheet href="https://cdn.jsdelivr.net/gh/u1ui/classless.css/classless.min.css">
<link rel=stylesheet href="https://cdn.jsdelivr.net/gh/u1ui/classless.css/more.min.css">
<link rel=stylesheet href="https://cdn.jsdelivr.net/gh/u1ui/classless.css/simple.min.css">
<script type=module src="../../u1/tests/test-init.js"></script>

<script src="../navigable.js" type=module></script>

Expand All @@ -27,13 +28,20 @@ <h1>Dialog</h1>

<section>
<h1>Checkbox</h1>

<input type=checkbox u1-navigable id=checkbox1>
<input type=checkbox u1-navigable id=checkbox2>
<input type=checkbox u1-navigable id=checkbox3>
</section>

<section>
<h1>Radiobutton</h1>
<input type=radio u1-navigable name=radio1 id=radio1>
<input type=radio u1-navigable name=radio1 id=radio2>
<input type=radio u1-navigable name=radio1 id=radio3>
</section>


<button u1-navigable-close>Close</button>
</dialog>

<dialog id="dialog2" u1-navigable>
Expand All @@ -48,7 +56,7 @@ <h1>Checkbox</h1>
<h1>Details</h1>

<a href="#details1">navigate to #details1</a>
<!--todo: button onclick="dialog1.showModal()">open by javascript</button-->
<!-- todo: <button onclick="dialog1.showModal()">open by javascript</button> -->

<details u1-navigable id=details1>
<summary>summary 1</summary>
Expand All @@ -61,12 +69,13 @@ <h1>Details</h1>

</section>

<!-- Ergänzung für Popover-Element -->
<section>
<h1>Popover</h1>
<button popovertarget="popover1">Toggle Popover</button>
<div id=popover1 popover u1-navigable>
<p>Popover content</p>
<button popovertarget="popover1" popovertargetaction="hide">Close</button>
</div>
</section>

<!--section>
<h1>Checkbox</h1>
<input type=checkbox u1-navigable id=checkbox1>
<input type=checkbox u1-navigable id=checkbox2>
<input type=checkbox u1-navigable id=checkbox3>
</section-->

0 comments on commit c01defb

Please sign in to comment.