u2ui 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.htaccess +7 -0
- package/LICENSE +21 -0
- package/README.md +36 -0
- package/attr/behavior/README.md +25 -0
- package/attr/behavior/behavior.js +261 -0
- package/attr/behavior/manifest.json +43 -0
- package/attr/behavior/tests/minimal.html +19 -0
- package/attr/behavior/tests/test.html +98 -0
- package/attr/confirm/README.md +36 -0
- package/attr/confirm/confirm.js +90 -0
- package/attr/confirm/manifest.json +43 -0
- package/attr/confirm/tests/minimal.html +23 -0
- package/attr/confirm/tests/test.html +79 -0
- package/attr/draghandle/README.md +41 -0
- package/attr/draghandle/draghandle.js +42 -0
- package/attr/draghandle/tests/minimal.html +44 -0
- package/attr/focusgroup/README.md +49 -0
- package/attr/focusgroup/focusgroup.js +100 -0
- package/attr/focusgroup/manifest.json +38 -0
- package/attr/focusgroup/tests/minimal.html +27 -0
- package/attr/focusgroup/tests/test.html +154 -0
- package/attr/href/README.md +38 -0
- package/attr/href/href.js +42 -0
- package/attr/href/manifest.json +43 -0
- package/attr/href/tests/minimal.html +17 -0
- package/attr/href/tests/test.html +70 -0
- package/attr/intersect/README.md +42 -0
- package/attr/intersect/intersect.js +99 -0
- package/attr/intersect/manifest.json +57 -0
- package/attr/intersect/tests/minimal.html +30 -0
- package/attr/intersect/tests/test.html +64 -0
- package/attr/navigable/README.md +31 -0
- package/attr/navigable/TargetObserver.js +91 -0
- package/attr/navigable/U2TargetObserver.js +75 -0
- package/attr/navigable/manifest.json +42 -0
- package/attr/navigable/navigable.js +87 -0
- package/attr/navigable/tests/U1TargetObserver.html +56 -0
- package/attr/navigable/tests/minimal.html +17 -0
- package/attr/navigable/tests/targetObserver.html +106 -0
- package/attr/navigable/tests/test.html +84 -0
- package/attr/parallax/README.md +48 -0
- package/attr/parallax/parallax.js +119 -0
- package/attr/parallax/tests/minimal.html +25 -0
- package/attr/parallax/tests/performance.html +102 -0
- package/attr/parallax/tests/test.html +108 -0
- package/attr/skin/README.md +59 -0
- package/attr/skin/skin.css +51 -0
- package/attr/skin/tests/minimal.html +34 -0
- package/attr/skin/tests/test.html +96 -0
- package/class/badge/README.md +25 -0
- package/class/badge/badge.css +35 -0
- package/class/badge/tests/minimal.html +17 -0
- package/class/badge/tests/test.html +112 -0
- package/class/card1/README.md +45 -0
- package/class/card1/card1.css +30 -0
- package/class/card1/tests/minimal.html +33 -0
- package/class/card1/tests/test.html +78 -0
- package/class/flex/README.md +62 -0
- package/class/flex/flex.css +25 -0
- package/class/flex/tests/minimal.html +31 -0
- package/class/flex/tests/test.html +58 -0
- package/class/grid/README.md +52 -0
- package/class/grid/grid.css +40 -0
- package/class/grid/tests/minimal.html +34 -0
- package/class/grid/tests/test.html +78 -0
- package/class/input/README.md +49 -0
- package/class/input/input.css +33 -0
- package/class/input/tests/minimal.html +39 -0
- package/class/input/tests/test.html +29 -0
- package/class/reset/README.md +47 -0
- package/class/reset/reset.css +8 -0
- package/class/reset/tests/minimal.html +23 -0
- package/class/table/README.md +57 -0
- package/class/table/table.css +126 -0
- package/class/table/tests/minimal.html +40 -0
- package/class/table/tests/test.html +226 -0
- package/class/unstyle/README.md +32 -0
- package/class/unstyle/tests/minimal.html +22 -0
- package/class/unstyle/tests/test.html +32 -0
- package/class/unstyle/unstyle.css +12 -0
- package/class/width/README.md +48 -0
- package/class/width/tests/minimal.html +27 -0
- package/class/width/tests/test.html +101 -0
- package/class/width/width.css +22 -0
- package/css/base/README.md +25 -0
- package/css/base/base.css +127 -0
- package/css/base/beta.css +50 -0
- package/css/base/full.css +5 -0
- package/css/base/nomotion.css +9 -0
- package/css/base/print.css +36 -0
- package/css/base/tests/nomotion.html +89 -0
- package/css/base/tests/test.html +539 -0
- package/css/classes/README.md +17 -0
- package/css/classes/classes.css +78 -0
- package/css/classes/tests/test.html +63 -0
- package/css/classless/README.md +26 -0
- package/css/classless/aria.css +64 -0
- package/css/classless/classless.css +124 -0
- package/css/classless/full.css +11 -0
- package/css/classless/more.css +340 -0
- package/css/classless/simple.css +103 -0
- package/css/classless/snippeds/a/icons.css +12 -0
- package/css/classless/snippeds/experiments/conventions.css +41 -0
- package/css/classless/snippeds/hr/gradient.css +3 -0
- package/css/classless/snippeds/hr/section_sign.css +16 -0
- package/css/classless/snippeds/hr/tests.html +50 -0
- package/css/classless/tests/aria.html +101 -0
- package/css/classless/tests/foreign/classless-almond.css.html +445 -0
- package/css/classless/tests/foreign/classless-classless.css.html +831 -0
- package/css/classless/tests/foreign/classless-mvp.html +415 -0
- package/css/classless/tests/foreign/classless.sakura.html +224 -0
- package/css/classless/tests/foreign/stylestage.dev.html +304 -0
- package/css/classless/tests/foreign/test-homogenizer.html +433 -0
- package/css/classless/tests/foreign/test-html5-elements-tester.html +956 -0
- package/css/classless/tests/foreign/test-opinionated_css.html +148 -0
- package/css/classless/tests/list-bullet.html +110 -0
- package/css/classless/tests/more.html +246 -0
- package/css/classless/tests/oklch.experiments.html +280 -0
- package/css/classless/tests/test.html +106 -0
- package/css/classless/tests/variables.html +109 -0
- package/css/classless/variables.css +99 -0
- package/css/norm/README.md +37 -0
- package/css/norm/beta.css +40 -0
- package/css/norm/norm.css +98 -0
- package/css/norm/oldies.css +60 -0
- package/css/norm/tests/test.html +434 -0
- package/css/norm/tests/test.js +103 -0
- package/el/accordion/README.md +59 -0
- package/el/accordion/accordion.css +7 -0
- package/el/accordion/accordion.js +258 -0
- package/el/accordion/manifest.json +57 -0
- package/el/accordion/tests/minimal.html +44 -0
- package/el/accordion/tests/test.html +168 -0
- package/el/alert/README.md +67 -0
- package/el/alert/alert copy.js +224 -0
- package/el/alert/alert.css +73 -0
- package/el/alert/alert.js +187 -0
- package/el/alert/manifest.json +77 -0
- package/el/alert/tests/minimal.html +36 -0
- package/el/alert/tests/test.html +105 -0
- package/el/buttongroup/README.md +36 -0
- package/el/buttongroup/buttongroup.css +30 -0
- package/el/buttongroup/buttongroup.js +56 -0
- package/el/buttongroup/tests/minimal.html +31 -0
- package/el/buttongroup/tests/test.html +83 -0
- package/el/bytes/README.md +41 -0
- package/el/bytes/bytes.css +6 -0
- package/el/bytes/bytes.js +97 -0
- package/el/bytes/manifest.json +95 -0
- package/el/bytes/tests/minimal.html +19 -0
- package/el/bytes/tests/test.html +117 -0
- package/el/carousel/README.md +52 -0
- package/el/carousel/carousel.css +46 -0
- package/el/carousel/carousel.js +371 -0
- package/el/carousel/manifest.json +58 -0
- package/el/carousel/tests/experiments.html +77 -0
- package/el/carousel/tests/minimal.html +31 -0
- package/el/carousel/tests/nested.html +54 -0
- package/el/carousel/tests/test.html +136 -0
- package/el/carousel-nav/README.md +40 -0
- package/el/carousel-nav/carousel-nav.js +74 -0
- package/el/carousel-nav/tests/minimal.html +32 -0
- package/el/carousel-nav/tests/test.html +59 -0
- package/el/code/README.md +68 -0
- package/el/code/code.css +46 -0
- package/el/code/code.js +289 -0
- package/el/code/manifest.json +66 -0
- package/el/code/tests/minimal.html +35 -0
- package/el/code/tests/test.html +162 -0
- package/el/copy/README.md +35 -0
- package/el/copy/copy.css +3 -0
- package/el/copy/copy.js +118 -0
- package/el/copy/manifest.json +49 -0
- package/el/copy/tests/minimal.html +21 -0
- package/el/copy/tests/test.html +75 -0
- package/el/counter/README.md +47 -0
- package/el/counter/counter.css +8 -0
- package/el/counter/counter.js +95 -0
- package/el/counter/manifest.json +59 -0
- package/el/counter/tests/minimal.html +27 -0
- package/el/counter/tests/test.html +106 -0
- package/el/ico/README.md +162 -0
- package/el/ico/font/Font Awesome.css +22 -0
- package/el/ico/font/LigatureSymbols.css +7 -0
- package/el/ico/font/Material Icons.css +6 -0
- package/el/ico/font/RemixFilled.css +8 -0
- package/el/ico/font/RemixOutlined.css +8 -0
- package/el/ico/font/old/anicons.css +31 -0
- package/el/ico/font/old/devicons.css +210 -0
- package/el/ico/font/old/material.all.css +36 -0
- package/el/ico/font/old/remix.css +15 -0
- package/el/ico/font/old/utf8.css +54 -0
- package/el/ico/ico.css +111 -0
- package/el/ico/ico.js +189 -0
- package/el/ico/manifest.json +86 -0
- package/el/ico/tests/combinations.html +86 -0
- package/el/ico/tests/emojis.html +213 -0
- package/el/ico/tests/fonts.html +110 -0
- package/el/ico/tests/ico-directory.html +254 -0
- package/el/ico/tests/minimal.html +46 -0
- package/el/ico/tests/test.html +210 -0
- package/el/ico/tests/util-multi.svg +6 -0
- package/el/ico/tests/util.css +2 -0
- package/el/ico/tests/util.js +110 -0
- package/el/input/README.md +39 -0
- package/el/input/input.css +35 -0
- package/el/input/input.js +331 -0
- package/el/input/tests/formParticipation.html +113 -0
- package/el/input/tests/minimal.html +33 -0
- package/el/input/tests/test.html +258 -0
- package/el/masonry/README.md +51 -0
- package/el/masonry/manifest.json +60 -0
- package/el/masonry/masonry.css +27 -0
- package/el/masonry/masonry.js +92 -0
- package/el/masonry/tests/minimal.html +39 -0
- package/el/masonry/tests/test.html +42 -0
- package/el/number/README.md +47 -0
- package/el/number/manifest.json +121 -0
- package/el/number/number.css +6 -0
- package/el/number/number.js +67 -0
- package/el/number/tests/minimal.html +25 -0
- package/el/number/tests/test.html +138 -0
- package/el/out/README.md +32 -0
- package/el/out/manifest.json +38 -0
- package/el/out/out.css +2 -0
- package/el/out/out.js +59 -0
- package/el/out/tests/minimal.html +25 -0
- package/el/out/tests/test.html +37 -0
- package/el/parallax-bg/README.md +36 -0
- package/el/parallax-bg/parallax-bg.css +13 -0
- package/el/parallax-bg/parallax-bg.js +186 -0
- package/el/parallax-bg/tests/bg.jpg +0 -0
- package/el/parallax-bg/tests/bg1.jpg +0 -0
- package/el/parallax-bg/tests/bg2.jpg +0 -0
- package/el/parallax-bg/tests/demo.html +88 -0
- package/el/parallax-bg/tests/minimal.html +30 -0
- package/el/parallax-bg/tests/test.html +64 -0
- package/el/parallax-bg/tests/visible.html +90 -0
- package/el/qrcode/README.md +38 -0
- package/el/qrcode/manifest.json +43 -0
- package/el/qrcode/package.json +22 -0
- package/el/qrcode/qrcode.css +13 -0
- package/el/qrcode/qrcode.js +46 -0
- package/el/qrcode/tests/minimal.html +26 -0
- package/el/qrcode/tests/test.html +31 -0
- package/el/rating/README.md +45 -0
- package/el/rating/manifest.json +65 -0
- package/el/rating/rating.css +11 -0
- package/el/rating/rating.js +139 -0
- package/el/rating/tests/minimal.html +26 -0
- package/el/rating/tests/tests.html +77 -0
- package/el/rte/README.md +37 -0
- package/el/rte/rte.css +9 -0
- package/el/rte/rte.js +56 -0
- package/el/rte/tests/minimal.html +25 -0
- package/el/rte/tests/test.html +37 -0
- package/el/skeleton/README.md +30 -0
- package/el/skeleton/manifest.json +51 -0
- package/el/skeleton/skeleton.css +61 -0
- package/el/skeleton/skeleton.js +72 -0
- package/el/skeleton/tests/minimal.html +22 -0
- package/el/skeleton/tests/test.html +22 -0
- package/el/splitbutton/README.md +39 -0
- package/el/splitbutton/splitbutton.css +48 -0
- package/el/splitbutton/splitbutton.js +26 -0
- package/el/splitbutton/tests/minimal.html +30 -0
- package/el/splitbutton/tests/test.html +68 -0
- package/el/splitpanel/README.md +39 -0
- package/el/splitpanel/manifest.json +49 -0
- package/el/splitpanel/splitpanel.css +17 -0
- package/el/splitpanel/splitpanel.js +116 -0
- package/el/splitpanel/tests/minimal.html +31 -0
- package/el/splitpanel/tests/tests.html +121 -0
- package/el/table/README.md +68 -0
- package/el/table/manifest.json +43 -0
- package/el/table/table.css +59 -0
- package/el/table/table.js +194 -0
- package/el/table/tests/minimal.html +38 -0
- package/el/table/tests/test.html +108 -0
- package/el/tabs/README.md +50 -0
- package/el/tabs/manifest.json +59 -0
- package/el/tabs/tabs.css +23 -0
- package/el/tabs/tabs.js +210 -0
- package/el/tabs/tests/minimal.html +35 -0
- package/el/tabs/tests/test.html +180 -0
- package/el/textfit/README.md +34 -0
- package/el/textfit/manifest.json +45 -0
- package/el/textfit/tests/minimal.html +25 -0
- package/el/textfit/tests/test.html +26 -0
- package/el/textfit/textfit.css +6 -0
- package/el/textfit/textfit.js +80 -0
- package/el/time/README.md +72 -0
- package/el/time/manifest.json +118 -0
- package/el/time/tests/minimal.html +19 -0
- package/el/time/tests/test.html +160 -0
- package/el/time/time copy.js +141 -0
- package/el/time/time.js +168 -0
- package/el/time/time.old.uhtml.js +129 -0
- package/el/tooltip/README.md +48 -0
- package/el/tooltip/manifest.json +69 -0
- package/el/tooltip/tests/minimal.html +25 -0
- package/el/tooltip/tests/test.html +178 -0
- package/el/tooltip/tooltip.css +97 -0
- package/el/tooltip/tooltip.js +82 -0
- package/el/tree1/README.md +111 -0
- package/el/tree1/manifest.json +78 -0
- package/el/tree1/tests/animated.html +134 -0
- package/el/tree1/tests/custom.html +51 -0
- package/el/tree1/tests/minimal.html +44 -0
- package/el/tree1/tests/test.html +260 -0
- package/el/tree1/tree1.css +26 -0
- package/el/tree1/tree1.js +265 -0
- package/el/typewriter/README.md +62 -0
- package/el/typewriter/manifest.json +66 -0
- package/el/typewriter/tests/minimal.html +25 -0
- package/el/typewriter/tests/test.html +78 -0
- package/el/typewriter/typewriter.css +6 -0
- package/el/typewriter/typewriter.js +166 -0
- package/el/typewriter/typewriter.mp3 +0 -0
- package/js/Placer/Placer.js +156 -0
- package/js/Placer/README.md +62 -0
- package/js/Placer/tests/minimal.html +34 -0
- package/js/Placer/tests/test.html +49 -0
- package/js/PointerObserver/PointerObserver.js +130 -0
- package/js/PointerObserver/README.md +34 -0
- package/js/PointerObserver/tests/minimal.html +29 -0
- package/js/PointerObserver/tests/test.html +35 -0
- package/js/SelectorObserver/README.md +47 -0
- package/js/SelectorObserver/SelectorObserver.js +201 -0
- package/js/SelectorObserver/tests/minimal.html +21 -0
- package/js/SelectorObserver/tests/test.html +57 -0
- package/js/SelectorObserver/tests/tests.html +161 -0
- package/js/contextmenu/README.md +93 -0
- package/js/contextmenu/contextmenu.js +336 -0
- package/js/contextmenu/tests/minimal.html +44 -0
- package/js/contextmenu/tests/test.html +131 -0
- package/js/dialog/README.md +49 -0
- package/js/dialog/dialog.js +261 -0
- package/js/dialog/notification.mp3 +0 -0
- package/js/dialog/tests/minimal.html +29 -0
- package/js/dialog/tests/notification.mp3 +0 -0
- package/js/dialog/tests/test.html +135 -0
- package/js/rte/README.md +44 -0
- package/js/rte/old/NodeCleaner.js +315 -0
- package/js/rte/old/Rte/Rte.mjs +316 -0
- package/js/rte/old/Rte/Rte.ui.items.mjs +543 -0
- package/js/rte/old/Rte/Rte.ui.mjs +154 -0
- package/js/rte/old/Rte/crossbrowser.mjs +323 -0
- package/js/rte/old/Rte/font/tinymce.svg +98 -0
- package/js/rte/old/Rte/font/tinymce.woff +0 -0
- package/js/rte/old/Rte/helpers.mjs +159 -0
- package/js/rte/old/Rte/htmlparser.mjs +178 -0
- package/js/rte/old/Rte/index.mjs +5 -0
- package/js/rte/old/Rte/main.css +189 -0
- package/js/rte/old/old.rte.js +132 -0
- package/js/rte/old/range-selection.old.js +394 -0
- package/js/rte/rte.js +7 -0
- package/js/rte/src/behavior.js +228 -0
- package/js/rte/src/events.js +73 -0
- package/js/rte/src/fixes.js +251 -0
- package/js/rte/src/range.js +472 -0
- package/js/rte/src/rte.js +72 -0
- package/js/rte/src/ui/items/ai.js +167 -0
- package/js/rte/src/ui/items/code.js +93 -0
- package/js/rte/src/ui/items/undo.js +183 -0
- package/js/rte/src/ui.items.js +571 -0
- package/js/rte/src/ui.js +269 -0
- package/js/rte/src/util/htmlparser.js +178 -0
- package/js/rte/src/util/indentHtml.js +48 -0
- package/js/rte/tests/ai.html +81 -0
- package/js/rte/tests/behavior.html +88 -0
- package/js/rte/tests/events.html +69 -0
- package/js/rte/tests/fixes.html +95 -0
- package/js/rte/tests/minimal.html +34 -0
- package/js/rte/tests/notes.md +6 -0
- package/js/rte/tests/range.html +167 -0
- package/js/rte/tests/selection-explorer.html +222 -0
- package/js/rte/tests/test.html +92 -0
- package/js/shortcut/README.md +33 -0
- package/js/shortcut/shortcut.js +89 -0
- package/js/shortcut/tests/minimal.html +23 -0
- package/js/shortcut/tests/test.html +68 -0
- package/package.json +12 -0
- package/u2/README.md +4 -0
- package/u2/auto.js +161 -0
- package/u2/auto.ui.js +85 -0
- package/u2/experiments/Waiter/test.html +132 -0
- package/u2/experiments/getElementByIdPromise/test.html +76 -0
- package/u2/experiments/patchInputValue.html +124 -0
- package/u2/experiments/radiobutton/test.html +75 -0
- package/u2/experiments/tests/test.html +223 -0
- package/u2/experiments/u1-responsive/responsive.js +62 -0
- package/u2/experiments/u1-responsive/test.html +65 -0
- package/u2/experiments/u2Element.js +139 -0
- package/u2/experiments/u2Element.test.html +47 -0
- package/u2/old-stuff/IterableWeakMap/mod.js +70 -0
- package/u2/old-stuff/css/onStyleSheet/mod.js +114 -0
- package/u2/old-stuff/css/onStyleSheet/monkeypatches.js +28 -0
- package/u2/old-stuff/css/onStyleSheet/test/include.css +19 -0
- package/u2/old-stuff/css/onStyleSheet/test/style-has-include.css +6 -0
- package/u2/old-stuff/css/onStyleSheet/test/style-no-include.css +3 -0
- package/u2/old-stuff/css/onStyleSheet/test/test.html +48 -0
- package/u2/old-stuff/css/parser/mod.js +182 -0
- package/u2/old-stuff/css/parser/parser_old/mod.js +128 -0
- package/u2/old-stuff/css/parser/parser_old/test.html +43 -0
- package/u2/old-stuff/css/parser/parser_old/util.js +22 -0
- package/u2/old-stuff/css/parser/style.html +52 -0
- package/u2/old-stuff/css/parser/test.html +38 -0
- package/u2/old-stuff/el/ai-texter/README.md +23 -0
- package/u2/old-stuff/el/ai-texter/ai-texter.css +12 -0
- package/u2/old-stuff/el/ai-texter/ai-texter.js +153 -0
- package/u2/old-stuff/el/ai-texter/tests/minimal.html +47 -0
- package/u2/old-stuff/el/ai-texter/tests/test.html +71 -0
- package/u2/old-stuff/init.js +38 -0
- package/u2/old-stuff/markHashLinks.js +51 -0
- package/u2/old-stuff/onElement/mod.js +73 -0
- package/u2/old-stuff/test-helpers/mod.js +36 -0
- package/u2/old-stuff/test-helpers/test.html +4 -0
- package/u2/old-stuff/tests/init.js.html +51 -0
- package/u2/old-stuff/viewport.js +64 -0
- package/u2/projects.json +468 -0
- package/u2/tests/boilerplate.html +46 -0
- package/u2/tests/kacheln.html +245 -0
- package/u2/tests/showcase.html +270 -0
- package/u2/tests/showcase2.html +157 -0
- package/u2/tests/test-init.js +35 -0
- package/u2/tests/test.html +355 -0
- package/u2/tools/baseElement.js +95 -0
- package/u2/tools/baseElement.test.html +119 -0
- package/u2/tools/ce-inspector.js +308 -0
- package/u2/tools/ce-inspector.test.html +66 -0
- package/u2/tools/ce-manfest-from-element.js +207 -0
- package/u2/tools/dev-iframe.js +213 -0
- package/u2/tools/dev-iframe.test.html +75 -0
- package/u2/tools/eventsExplorer.js +101 -0
- package/u2/tools/logo/u1.svg +9 -0
- package/u2/tools/logo/u1ui.svg +6 -0
- package/u2/tools/update.repos.json.js +234 -0
- package/u2/u2.js +14 -0
- package/u2/utils.js +59 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/* Copyright (c) 2016 Tobias Buschor https://goo.gl/gl0mbf | MIT License https://goo.gl/HgajeK */
|
|
2
|
+
|
|
3
|
+
document.addEventListener('click', e => {
|
|
4
|
+
if (e.button !== 0) return; // only left-click
|
|
5
|
+
if (e.defaultPrevented) return; // not if prevented
|
|
6
|
+
const sel = getSelection();
|
|
7
|
+
if (!sel.isCollapsed) { // only if the selection is collapsed.
|
|
8
|
+
const textSelected = sel.anchorNode.nodeType === 3 || sel.focusNode.nodeType === 3;
|
|
9
|
+
const shadowElSelected = sel.focusNode.nodeType === 11; // svg-use-element, firefox
|
|
10
|
+
if (textSelected && !shadowElSelected) return;
|
|
11
|
+
}
|
|
12
|
+
if (!e.target.closest) return; // some targets have no closest method?
|
|
13
|
+
const A = e.target.closest('[u2-href]');
|
|
14
|
+
if (!A) return;
|
|
15
|
+
if (e.target.closest('a,input,textarea,select,button,label')) return;
|
|
16
|
+
//if (e.target.closest('[onclick]')) return; //
|
|
17
|
+
//if (e.target.closest(c1.href.ignoreSelector)) return;
|
|
18
|
+
if (e.target.isContentEditable) return; // not if contenteditable
|
|
19
|
+
const href = A.getAttribute('u2-href'); // get the url
|
|
20
|
+
if (!href) return;
|
|
21
|
+
|
|
22
|
+
const url = new URL(href, location.href); // security check, as its not a standard attribute, puryfiers will probably not remove it
|
|
23
|
+
if (url.protocol === 'javascript:') return;
|
|
24
|
+
|
|
25
|
+
let target = A.getAttribute('u2-href-target'); // get the target
|
|
26
|
+
if (e.ctrlKey) target = '_blank'; // better random-string?
|
|
27
|
+
// var event = new CustomEvent('u2-href-navigate', { // trigger custom event with the ability to prevent Navigation
|
|
28
|
+
// cancelable: true,
|
|
29
|
+
// detail: {
|
|
30
|
+
// url: href,
|
|
31
|
+
// target: target,
|
|
32
|
+
// }
|
|
33
|
+
// });
|
|
34
|
+
// window.dispatchEvent(event);
|
|
35
|
+
// if (event.defaultPrevented) return;
|
|
36
|
+
if (target) {
|
|
37
|
+
window.open(href, target, 'noopener'); //!e.ctrlKey && win.focus(); // not needed in chrome, not working in ff
|
|
38
|
+
} else {
|
|
39
|
+
location.href = href;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
document.head.insertAdjacentHTML('afterbegin', '<style>:where([u2-href]){cursor:pointer}</style>');
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0.0",
|
|
3
|
+
"readme": "README.md",
|
|
4
|
+
"modules": [
|
|
5
|
+
{
|
|
6
|
+
"kind": "javascript-module",
|
|
7
|
+
"path": "href.js",
|
|
8
|
+
"declarations": [
|
|
9
|
+
{
|
|
10
|
+
"summary": "Turn every element in a link",
|
|
11
|
+
"description": "This attribute allows you to turn any element into a link by simply adding the `u2-href` attribute to it.\n`Ctrl + click` will open the link in a new tab.\nClicks on interactive elements inside the pseudo-link element prevent the link from being opened.\nXSS attacks are prevented by disallowing the `javascript:` protocol.",
|
|
12
|
+
"name": "u2-href",
|
|
13
|
+
"members": [],
|
|
14
|
+
"events": [],
|
|
15
|
+
"attributes": [
|
|
16
|
+
{
|
|
17
|
+
"name": "u2-href",
|
|
18
|
+
"description": "The URL that the hyperlink points to.",
|
|
19
|
+
"u2Examples": ["", "https://www.google.com", "./test.html", "#section1"]
|
|
20
|
+
},{
|
|
21
|
+
"name": "u2-href-target",
|
|
22
|
+
"description": "The target attribute specifies where to open the linked document.",
|
|
23
|
+
"u2Examples": ["_blank", "myFrame"]
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"cssProperties": [],
|
|
27
|
+
"attributeName": "u2-href"
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"exports": [
|
|
31
|
+
{
|
|
32
|
+
"kind": "custom-attribute-definition",
|
|
33
|
+
"name": "u2-href",
|
|
34
|
+
"declaration": {
|
|
35
|
+
"name": "u2-href",
|
|
36
|
+
"module": "href.js"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang=en>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset=utf-8>
|
|
5
|
+
<meta name=viewport content="width=device-width">
|
|
6
|
+
<script src="../../../u2/tests/test-init.js" type=module async></script>
|
|
7
|
+
|
|
8
|
+
<script src="../href.js" type=module async></script>
|
|
9
|
+
|
|
10
|
+
<body>
|
|
11
|
+
|
|
12
|
+
<section class=main>
|
|
13
|
+
<div u2-href="http://schwups.ch" u2-href-target=_blank>
|
|
14
|
+
Pseudo link
|
|
15
|
+
</div>
|
|
16
|
+
</section>
|
|
17
|
+
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width">
|
|
6
|
+
<script src="../../../u2/tests/test-init.js" type=module async></script>
|
|
7
|
+
<title>Attribute u2-href tests</title>
|
|
8
|
+
|
|
9
|
+
<link rel=stylesheet href="../../../css/classless/full.css">
|
|
10
|
+
<link rel=stylesheet href="../../../css/classless/simple.css">
|
|
11
|
+
|
|
12
|
+
<script src="../href.js"></script>
|
|
13
|
+
|
|
14
|
+
<body>
|
|
15
|
+
|
|
16
|
+
<div u2-href="https://github.com/u2ui" class=pseudoLink>
|
|
17
|
+
<h1>I am a DIV and i act like a link</h1>
|
|
18
|
+
<ul>
|
|
19
|
+
<li>Elements using the u2-href-attribute have a cursor:pointer</li>
|
|
20
|
+
<li>Try <mark>ctrl-click</mark>, the link shoul open in a new tab</li>
|
|
21
|
+
<li>Try <mark>right or middle mouse button</mark> the link does not work</li>
|
|
22
|
+
<li>If you <mark>Select some text</mark> the link does not work</li>
|
|
23
|
+
<li>
|
|
24
|
+
<button> if you click the button, the u2-href does not work</button>
|
|
25
|
+
</li>
|
|
26
|
+
<li>
|
|
27
|
+
<label>
|
|
28
|
+
Label
|
|
29
|
+
<input value="and inputs also prevents navigation" style="width:200px">
|
|
30
|
+
</label>
|
|
31
|
+
</li>
|
|
32
|
+
<li contenteditable>
|
|
33
|
+
I am contenteditable, h1-href does not navigate
|
|
34
|
+
</li>
|
|
35
|
+
<li onclick="event.preventDefault()">I am a li that prevents the click-default, it also prevents c1-href from navigate (<code>onclick="event.preventDefault()"</code>)</li>
|
|
36
|
+
</ul>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<div u2-href="https://github.com/u2ui" u2-href-target=_blank class=pseudoLink>
|
|
40
|
+
A u2-href link with the attribute <code>u2-href-target="_blank"</code><br>
|
|
41
|
+
Opens in a new window
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
<div u2-href="https://github.com/u2ui" class=pseudoLink tabindex="0">
|
|
46
|
+
This u2-href link is keyboard-accessible through it has "tabindex"-attribute<br>
|
|
47
|
+
It will not trigger navigation if it is focused and you press enter, should it?<br>
|
|
48
|
+
If you have usecase, please let me know.
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
<div u2-href="./" class=pseudoLink>
|
|
53
|
+
relative links "./"
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<div u2-href="  jAvascript:alert('xss')" class=pseudoLink>
|
|
57
|
+
security, should not execute u2-href=" &#14; jAvascript:alert('xss')"
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<style>
|
|
61
|
+
li {
|
|
62
|
+
padding:1rem;
|
|
63
|
+
}
|
|
64
|
+
.pseudoLink {
|
|
65
|
+
margin:1rem;
|
|
66
|
+
border:1px solid red;
|
|
67
|
+
background:#ffe;
|
|
68
|
+
padding:1rem;
|
|
69
|
+
}
|
|
70
|
+
</style>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# [u2-intersect] - attribute
|
|
2
|
+
declarativ intersection-observer
|
|
3
|
+
|
|
4
|
+
## Usage
|
|
5
|
+
|
|
6
|
+
```html
|
|
7
|
+
<div u2-intersect>intersect</div>
|
|
8
|
+
<div u2-intersect>item 2</div>
|
|
9
|
+
<div u2-intersect>item 3</div>
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
```css
|
|
13
|
+
[u2-intersect] {
|
|
14
|
+
--u2-intersect-margin:-10%;
|
|
15
|
+
--u2-intersect-threshold:1;
|
|
16
|
+
background:#fbb;
|
|
17
|
+
}
|
|
18
|
+
[u2-intersect].u2-intersected { background:#bfb; }
|
|
19
|
+
[u2-intersect]::after {
|
|
20
|
+
display:block;
|
|
21
|
+
content:'below';
|
|
22
|
+
}
|
|
23
|
+
[u2-intersect].u2-intersected::after { content:'intersected'; }
|
|
24
|
+
[u2-intersect~="above"]::after { content:'above' }
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<script src="https://cdn.jsdelivr.net/gh/u2ui/u2@x.x.x/attr/intersect/intersect.min.js" type=module async></script>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Demos
|
|
34
|
+
|
|
35
|
+
[minimal.html](http://gcdn.li/u2ui/u2@main/attr/intersect/tests/minimal.html)
|
|
36
|
+
[test.html](http://gcdn.li/u2ui/u2@main/attr/intersect/tests/test.html)
|
|
37
|
+
|
|
38
|
+
## About
|
|
39
|
+
|
|
40
|
+
- MIT License, Copyright (c) 2022 <u2> (like all repositories in this organization) <br>
|
|
41
|
+
- Suggestions, ideas, finding bugs and making pull requests make us very happy. ♥
|
|
42
|
+
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/* Copyright (c) 2016 Tobias Buschor https://goo.gl/gl0mbf | MIT License https://goo.gl/HgajeK */
|
|
2
|
+
|
|
3
|
+
import {SelectorObserver} from '../../js/SelectorObserver/SelectorObserver.js'
|
|
4
|
+
|
|
5
|
+
new SelectorObserver({
|
|
6
|
+
on: (el) => {
|
|
7
|
+
//const el = this.element;
|
|
8
|
+
const style = getComputedStyle(el);
|
|
9
|
+
const threshold = parseFloat(style.getPropertyValue('--u2-intersect-threshold').trim()) || 0;
|
|
10
|
+
const margin = style.getPropertyValue('--u2-intersect-margin') || '0px';
|
|
11
|
+
|
|
12
|
+
const thresholds = new Set([threshold, 0, 1, 0.5]);
|
|
13
|
+
|
|
14
|
+
el.u2IntersectionObserver = new IntersectionObserver(entries=>{
|
|
15
|
+
let attrValue = '';
|
|
16
|
+
const entry = entries[0];
|
|
17
|
+
let ratio = entry.intersectionRatio;
|
|
18
|
+
let onTarget = false;
|
|
19
|
+
if (entry.isIntersecting) {
|
|
20
|
+
for (const val of thresholds) {
|
|
21
|
+
if (ratio >= val) attrValue += ' '+val;
|
|
22
|
+
}
|
|
23
|
+
if (ratio >= threshold) onTarget = true;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
if (entry.boundingClientRect.top + entry.boundingClientRect.height / 2 < innerHeight / 2) {
|
|
28
|
+
attrValue += ' above';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
attrValue = attrValue.trim();
|
|
32
|
+
el.setAttribute('u2-intersect', attrValue);
|
|
33
|
+
el.classList[onTarget?'add':'remove']('u2-intersected');
|
|
34
|
+
|
|
35
|
+
const event = new CustomEvent('u2-intersect.'+(onTarget?'enter':'leave'), {bubbles:true} );
|
|
36
|
+
el.dispatchEvent(event);
|
|
37
|
+
}, {
|
|
38
|
+
//root: document.scrollingElement,
|
|
39
|
+
rootMargin: margin,
|
|
40
|
+
threshold: thresholds,
|
|
41
|
+
});
|
|
42
|
+
el.u2IntersectionObserver.observe(el);
|
|
43
|
+
|
|
44
|
+
},
|
|
45
|
+
off: (el) => {
|
|
46
|
+
if (el.u2IntersectionObserver) el.u2IntersectionObserver.unobserve(el);
|
|
47
|
+
}
|
|
48
|
+
}).observe('[u2-intersect]');
|
|
49
|
+
|
|
50
|
+
/*
|
|
51
|
+
old code:
|
|
52
|
+
import 'https://cdn.jsdelivr.net/npm/wicked-elements@3.1.2/min.js';
|
|
53
|
+
wickedElements.define(
|
|
54
|
+
'[u2-intersect]', {
|
|
55
|
+
init() {},
|
|
56
|
+
connected() {
|
|
57
|
+
const el = this.element;
|
|
58
|
+
const style = getComputedStyle(el);
|
|
59
|
+
const threshold = parseFloat(style.getPropertyValue('--u2-intersect-threshold').trim()) || 0;
|
|
60
|
+
const margin = style.getPropertyValue('--u2-intersect-margin') || '0px';
|
|
61
|
+
|
|
62
|
+
const thresholds = new Set([threshold, 0, 1, 0.5]);
|
|
63
|
+
|
|
64
|
+
this.u2IntersectionObserver = new IntersectionObserver(entries=>{
|
|
65
|
+
let attrValue = '';
|
|
66
|
+
const entry = entries[0];
|
|
67
|
+
let ratio = entry.intersectionRatio;
|
|
68
|
+
let onTarget = false;
|
|
69
|
+
if (entry.isIntersecting) {
|
|
70
|
+
for (const val of thresholds) {
|
|
71
|
+
if (ratio >= val) attrValue += ' '+val;
|
|
72
|
+
}
|
|
73
|
+
if (ratio >= threshold) onTarget = true;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
if (entry.boundingClientRect.top + entry.boundingClientRect.height / 2 < innerHeight / 2) {
|
|
78
|
+
attrValue += ' above';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
attrValue = attrValue.trim();
|
|
82
|
+
el.setAttribute('u2-intersect', attrValue);
|
|
83
|
+
el.classList[onTarget?'add':'remove']('u2-intersected');
|
|
84
|
+
|
|
85
|
+
//var event = new CustomEvent('u2-intersected-'+(onTarget?'in':'out'), /*{bubbles:true}* / );
|
|
86
|
+
//el.dispatchEvent(event);
|
|
87
|
+
}, {
|
|
88
|
+
//root: document.scrollingElement,
|
|
89
|
+
rootMargin: margin,
|
|
90
|
+
threshold: thresholds,
|
|
91
|
+
});
|
|
92
|
+
this.u2IntersectionObserver.observe(el);
|
|
93
|
+
},
|
|
94
|
+
disconnected() {
|
|
95
|
+
this.u2IntersectionObserver.unobserve(el);
|
|
96
|
+
},
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
*/
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0.0",
|
|
3
|
+
"readme": "README.md",
|
|
4
|
+
"modules": [
|
|
5
|
+
{
|
|
6
|
+
"kind": "javascript-module",
|
|
7
|
+
"path": "intersect.js",
|
|
8
|
+
"declarations": [
|
|
9
|
+
{
|
|
10
|
+
"summary": "Declarativ intersection-observer",
|
|
11
|
+
"description": "This attribute allows you to turn any element into a link by simply adding the `u2-intersect` attribute to it.\n`Ctrl + click` will open the link in a new tab.\nClicks on interactive elements inside the pseudo-link element prevent the link from being opened.\nXSS attacks are prevented by disallowing the `javascript:` protocol.",
|
|
12
|
+
"name": "u2-intersect",
|
|
13
|
+
"members": [],
|
|
14
|
+
"events": [
|
|
15
|
+
{
|
|
16
|
+
"name": "u2-intersect.enter",
|
|
17
|
+
"description": "Fired when the element intersects with the viewport."
|
|
18
|
+
},{
|
|
19
|
+
"name": "u2-intersect.leave",
|
|
20
|
+
"description": "Fired when the element leaves the viewport."
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"attributes": [
|
|
24
|
+
{
|
|
25
|
+
"name": "u2-intersect",
|
|
26
|
+
"description": "Enables the intersection observer on the element.",
|
|
27
|
+
"u2Examples": ["", "https://www.google.com", "./test.html", "#section1"]
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"cssProperties": [
|
|
31
|
+
{
|
|
32
|
+
"name": "--u2-intersect-margin",
|
|
33
|
+
"description": "The margin around the element that will trigger the intersection observer.",
|
|
34
|
+
"syntax": "<length>"
|
|
35
|
+
},{
|
|
36
|
+
"name": "--u2-intersect-threshold",
|
|
37
|
+
"description": "The threshold at which the intersection observer will trigger.",
|
|
38
|
+
"syntax": "<number>"
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"attributeName": "u2-intersect"
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
"exports": [
|
|
45
|
+
{
|
|
46
|
+
"kind": "custom-attribute-definition",
|
|
47
|
+
"name": "u2-intersect",
|
|
48
|
+
"declaration": {
|
|
49
|
+
"name": "u2-intersect",
|
|
50
|
+
"module": "intersect.js"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang=en>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset=utf-8>
|
|
5
|
+
<meta name=viewport content="width=device-width">
|
|
6
|
+
|
|
7
|
+
<script src="../intersect.js" type=module async></script>
|
|
8
|
+
|
|
9
|
+
<body>
|
|
10
|
+
|
|
11
|
+
<section class="main">
|
|
12
|
+
<div u2-intersect>intersect</div>
|
|
13
|
+
<div u2-intersect>item 2</div>
|
|
14
|
+
<div u2-intersect>item 3</div>
|
|
15
|
+
</section>
|
|
16
|
+
|
|
17
|
+
<style class="main">
|
|
18
|
+
[u2-intersect] {
|
|
19
|
+
--u2-intersect-margin:-10%;
|
|
20
|
+
--u2-intersect-threshold:1;
|
|
21
|
+
background:#fbb;
|
|
22
|
+
}
|
|
23
|
+
[u2-intersect].u2-intersected { background:#bfb; }
|
|
24
|
+
[u2-intersect]::after {
|
|
25
|
+
display:block;
|
|
26
|
+
content:'below';
|
|
27
|
+
}
|
|
28
|
+
[u2-intersect].u2-intersected::after { content:'intersected'; }
|
|
29
|
+
[u2-intersect~="above"]::after { content:'above' }
|
|
30
|
+
</style>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width">
|
|
6
|
+
<title>Attribute u2-href tests</title>
|
|
7
|
+
|
|
8
|
+
<link rel=stylesheet href="../../../css/classless/full.css">
|
|
9
|
+
<!--link rel=stylesheet href="../../../css/classless/simple.css"-->
|
|
10
|
+
|
|
11
|
+
<script src="../intersect.js" type=module async></script>
|
|
12
|
+
|
|
13
|
+
<body>
|
|
14
|
+
|
|
15
|
+
<style>
|
|
16
|
+
[u2-intersect] {
|
|
17
|
+
border:2px solid;
|
|
18
|
+
padding:2rem;
|
|
19
|
+
margin:5rem auto;
|
|
20
|
+
background:red;
|
|
21
|
+
width:50%;
|
|
22
|
+
}
|
|
23
|
+
[u2-intersect].u2-intersected {
|
|
24
|
+
background:green;
|
|
25
|
+
}
|
|
26
|
+
[u2-intersect~="above"] {
|
|
27
|
+
background:orange;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
</style>
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
<div style="position:fixed; top:0; left:0; right:0; bottom:0; opacity:0.2; z-index:-1; border:20vh solid #A49CE1; border-width:20vh 20vw"></div>
|
|
34
|
+
|
|
35
|
+
<div>
|
|
36
|
+
<div u2-intersect style="height:20vh; --u2-intersect-margin:0%; --u2-intersect-threshold:0;" >
|
|
37
|
+
--u2-intersect-margin:0;<br>
|
|
38
|
+
--u2-intersect-threshold:0;
|
|
39
|
+
</div>
|
|
40
|
+
<div u2-intersect style="height:20vh; --u2-intersect-margin:-20%; --u2-intersect-threshold:0;" >
|
|
41
|
+
--u2-intersect-margin:-20%;<br>
|
|
42
|
+
--u2-intersect-threshold:0;
|
|
43
|
+
</div>
|
|
44
|
+
<div u2-intersect style="height:20vh; --u2-intersect-margin:-20%; --u2-intersect-threshold:1;" >
|
|
45
|
+
--u2-intersect-margin:-20%;<br>
|
|
46
|
+
--u2-intersect-threshold:1;
|
|
47
|
+
</div>
|
|
48
|
+
<div u2-intersect style="height:20vh; --u2-intersect-margin:-20%; --u2-intersect-threshold:0.25;" >
|
|
49
|
+
--u2-intersect-margin:-20%;<br>
|
|
50
|
+
--u2-intersect-threshold:0.25;
|
|
51
|
+
</div>
|
|
52
|
+
<div u2-intersect style="height:20vh;" class=selector1>
|
|
53
|
+
<style style="display:block; font-size:.9rem">
|
|
54
|
+
.selector1:not([u2-intersect~="0.5"]) {
|
|
55
|
+
background:red;
|
|
56
|
+
}
|
|
57
|
+
.selector1:not([u2-intersect~="0.5"])[u2-intersect~="above"] {
|
|
58
|
+
background:orange;
|
|
59
|
+
}
|
|
60
|
+
</style>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<div style="height:100vh"></div>
|
|
64
|
+
</div>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# [u2-navigable] - attribute
|
|
2
|
+
Make elements navigatable
|
|
3
|
+
|
|
4
|
+
## Usage
|
|
5
|
+
|
|
6
|
+
```html
|
|
7
|
+
Link to navigable dialog:<br>
|
|
8
|
+
<a href="#navigable">open</a>
|
|
9
|
+
<dialog u2-navigable id=navigable>
|
|
10
|
+
go back using esc or your browser's back button
|
|
11
|
+
</dialog>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```html
|
|
17
|
+
<script src="https://cdn.jsdelivr.net/gh/u2ui/u2@x.x.x/attr/navigable/navigable.min.js" type=module async></script>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Demos
|
|
21
|
+
|
|
22
|
+
[minimal.html](http://gcdn.li/u2ui/u2@main/attr/navigable/tests/minimal.html)
|
|
23
|
+
[targetObserver.html](http://gcdn.li/u2ui/u2@main/attr/navigable/tests/targetObserver.html)
|
|
24
|
+
[test.html](http://gcdn.li/u2ui/u2@main/attr/navigable/tests/test.html)
|
|
25
|
+
[U1TargetObserver.html](http://gcdn.li/u2ui/u2@main/attr/navigable/tests/U1TargetObserver.html)
|
|
26
|
+
|
|
27
|
+
## About
|
|
28
|
+
|
|
29
|
+
- MIT License, Copyright (c) 2022 <u2> (like all repositories in this organization) <br>
|
|
30
|
+
- Suggestions, ideas, finding bugs and making pull requests make us very happy. ♥
|
|
31
|
+
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// checks for hashchange and element matches
|
|
2
|
+
|
|
3
|
+
const observers = new Set();
|
|
4
|
+
|
|
5
|
+
export class TargetObserver {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {Object} opts
|
|
9
|
+
* @param {Function} opts.on - called when a element is the target
|
|
10
|
+
* @param {Function} opts.off - called when a element lost the target
|
|
11
|
+
* @param {Function} opts.in - called when a element or a descendant is the target
|
|
12
|
+
* @param {Function} opts.out - called when a element lost the target including descendants
|
|
13
|
+
* @param {String} opts.matches - CSS selector for elements we listen to
|
|
14
|
+
*/
|
|
15
|
+
constructor(opts) {
|
|
16
|
+
this.opts = opts;
|
|
17
|
+
observers.add(this);
|
|
18
|
+
this.parentTargets = new Set();
|
|
19
|
+
this._testOn(active);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @description stops listening
|
|
24
|
+
*/
|
|
25
|
+
disconnect() {
|
|
26
|
+
observers.delete(this);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {Element} el
|
|
31
|
+
* @private
|
|
32
|
+
*/
|
|
33
|
+
_matches(el){
|
|
34
|
+
if (!el) return false;
|
|
35
|
+
return this.opts.matches==null || el.matches(this.opts.matches);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @param {Element} el
|
|
40
|
+
* @private
|
|
41
|
+
*/
|
|
42
|
+
_testOn(el){
|
|
43
|
+
this.opts.on && this._matches(el) && this.opts.on(el);
|
|
44
|
+
if (this.opts.in && el) { // todo: && this.opts.matches ??
|
|
45
|
+
let closest = el.closest(this.opts.matches);
|
|
46
|
+
while (closest) {
|
|
47
|
+
this.opts.in(closest);
|
|
48
|
+
this.parentTargets.add(closest);
|
|
49
|
+
closest = closest.parentNode.closest(this.opts.matches);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
for (const pTarget of this.parentTargets) {
|
|
53
|
+
if (el && pTarget.contains(el)) continue;
|
|
54
|
+
this.opts?.out(pTarget);
|
|
55
|
+
this.parentTargets.delete(pTarget);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @param {Element} el
|
|
61
|
+
* @private
|
|
62
|
+
*/
|
|
63
|
+
_testOff(el){
|
|
64
|
+
this.opts.off && this._matches(el) && this.opts.off(el);
|
|
65
|
+
this.opts.out && this._matches(el) && this.opts.out(el);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let active = null;
|
|
70
|
+
|
|
71
|
+
function checkTarget(e) {
|
|
72
|
+
const target = location.hash ? document.getElementById(location.hash.substring(1)) : false;
|
|
73
|
+
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
|
|
74
|
+
if (!changed) return;
|
|
75
|
+
for (const observer of observers) {
|
|
76
|
+
observer._testOff(active);
|
|
77
|
+
observer._testOn(target);
|
|
78
|
+
}
|
|
79
|
+
active = target;
|
|
80
|
+
}
|
|
81
|
+
checkTarget();
|
|
82
|
+
addEventListener('hashchange', checkTarget);
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
// Usage:
|
|
86
|
+
// const observer = new TargetObserver({
|
|
87
|
+
// in: (target) => console.log(target),
|
|
88
|
+
// out: (target) => console.log(target),
|
|
89
|
+
// matches: '.element', // optional
|
|
90
|
+
// })
|
|
91
|
+
// observer.disconnect();
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// checks for the "u2-target" query parameter and calls the on/off functions
|
|
2
|
+
// e.g. ?u2-target=details1+checkbox3+dialog1
|
|
3
|
+
|
|
4
|
+
const observers = new Set();
|
|
5
|
+
|
|
6
|
+
export class U2TargetObserver {
|
|
7
|
+
constructor(opts) {
|
|
8
|
+
this.opts = opts;
|
|
9
|
+
observers.add(this);
|
|
10
|
+
|
|
11
|
+
this._testOns(actives);
|
|
12
|
+
}
|
|
13
|
+
disconnect() {
|
|
14
|
+
observers.delete(this);
|
|
15
|
+
}
|
|
16
|
+
_matches(el){
|
|
17
|
+
if (!el) return false;
|
|
18
|
+
return el!==false && this.opts.matches==null || el.matches(this.opts.matches);
|
|
19
|
+
}
|
|
20
|
+
_testOn(el){
|
|
21
|
+
this.opts.on && this._matches(el) && this.opts.on(el);
|
|
22
|
+
}
|
|
23
|
+
_testOff(el){
|
|
24
|
+
this.opts.off && this._matches(el) && this.opts.off(el);
|
|
25
|
+
}
|
|
26
|
+
_testOns(els){
|
|
27
|
+
for (const el of els) this._testOn(el);
|
|
28
|
+
}
|
|
29
|
+
_testOffs(els){
|
|
30
|
+
for (const el of els) this._testOff(el);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let actives = new Set();
|
|
35
|
+
|
|
36
|
+
function checkTargets(){
|
|
37
|
+
const newest = new Set();
|
|
38
|
+
const param = new URL(location).searchParams.get('u2-target');
|
|
39
|
+
if (param) {
|
|
40
|
+
for (const item of param.split(' ')) {
|
|
41
|
+
const el = item && document.getElementById(item);
|
|
42
|
+
el && newest.add(el);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const added = new Set();
|
|
47
|
+
const removed = new Set();
|
|
48
|
+
for (let item of actives) if (!newest.has(item)) removed.add(item);
|
|
49
|
+
for (let item of newest) if (!actives.has(item)) added.add(item);
|
|
50
|
+
for (const obs of observers) {
|
|
51
|
+
obs._testOffs(removed);
|
|
52
|
+
obs._testOns(added);
|
|
53
|
+
}
|
|
54
|
+
actives = newest;
|
|
55
|
+
}
|
|
56
|
+
addEventListener('popstate', checkTargets);
|
|
57
|
+
checkTargets();
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
// Possible improvement:
|
|
61
|
+
// Initial TargetObserver tiggers if in url, then toggle-event triggers, resulting in toggleParam without a need.
|
|
62
|
+
// Can we solve this?
|
|
63
|
+
|
|
64
|
+
// togglelParam
|
|
65
|
+
export function toggleParam(id, force, replace){
|
|
66
|
+
const url = new URL(location);
|
|
67
|
+
const targets = new Set((url.searchParams.get('u2-target')||'').split(' '));
|
|
68
|
+
const isPresent = targets.has(id);
|
|
69
|
+
const shouldAdd = force ?? !isPresent;
|
|
70
|
+
if (shouldAdd === isPresent) return;
|
|
71
|
+
shouldAdd ? targets.add(id) : targets.delete(id);
|
|
72
|
+
url.searchParams.set('u2-target', [...targets].join(' '));
|
|
73
|
+
history[replace?'replaceState':'pushState'](null, '', url.href);
|
|
74
|
+
checkTargets();
|
|
75
|
+
}
|