1
0
mirror of https://github.com/jaandrle/deka-dom-el synced 2024-11-25 01:39:37 +01:00

🐛 Try to make undefined more inuitive…

…(as it is ‘template lang’ not only `assign`)
This commit is contained in:
Jan Andrle 2023-09-13 13:02:17 +02:00
parent a7b3ea633b
commit 5436e50a95
Signed by: jaandrle
GPG Key ID: B3A25AED155AFFAB
7 changed files with 38 additions and 7 deletions

18
src/dom-common.js Normal file
View File

@ -0,0 +1,18 @@
/** @type {Map<string, boolean>} */
export const prop_cache= new Map(JSON.parse('[["#text,textContent",true],["HTMLElement,textContent",true],["HTMLElement,className",true]]'));
export const prop_process= { setDelete };
import { isUndef } from './helpers.js';
function setDelete(obj, prop, val){
/* Issue
For some native attrs you can unset only to set empty string.
This can be confusing as it is seen in inspector `<… id=""`.
Options:
1. Leave it, as it is native behaviour
2. Sets as empty string and removes the corresponding attribute when also has empty string
*3. Sets as undefined and removes the corresponding attribute when "undefined" string discovered
4. Point 2. with checks for coincidence (e.g. use special string)
*/
Reflect.set(obj, prop, val);
if(isUndef(val) && obj.getAttribute(prop)==="undefined")
obj.removeAttribute(prop);
}

View File

@ -30,8 +30,8 @@ export function createElement(tag, attributes, ...connect){
} }
export { createElement as el }; export { createElement as el };
/** @type {Map<string, boolean>} */ import { prop_cache, prop_process } from './dom-common.js';
const prop_cache= new Map(JSON.parse('[["#text,textContent",true],["HTMLElement,textContent",true],["HTMLElement,className",true]]')); const { setDelete }= prop_process;
export function assign(element, ...attributes){ export function assign(element, ...attributes){
const s= signals(this); const s= signals(this);
if(!attributes.length) return element; if(!attributes.length) return element;
@ -82,6 +82,7 @@ export function empty(el){
Array.from(el.children).forEach(el=> el.remove()); Array.from(el.children).forEach(el=> el.remove());
return el; return el;
} }
import { isUndef } from "./helpers.js";
function isPropSetter(el, key){ function isPropSetter(el, key){
const cache_key_he= "HTMLElement,"+key; const cache_key_he= "HTMLElement,"+key;
if(el instanceof HTMLElement && prop_cache.has(cache_key_he)) if(el instanceof HTMLElement && prop_cache.has(cache_key_he))
@ -104,8 +105,6 @@ function getPropDescriptor(p, key, level= 0){
/** @template {Record<any, any>} T @param {T} obj @param {(param: [ keyof T, T[keyof T] ])=> void} cb */ /** @template {Record<any, any>} T @param {T} obj @param {(param: [ keyof T, T[keyof T] ])=> void} cb */
function forEachEntries(obj, cb){ return Object.entries(obj).forEach(([ key, val ])=> cb(key, val)); } function forEachEntries(obj, cb){ return Object.entries(obj).forEach(([ key, val ])=> cb(key, val)); }
function isUndef(value){ return typeof value==="undefined"; }
function setRemove(obj, prop, key, val){ return obj[ (isUndef(val) ? "remove" : "set") + prop ](key, val); } function setRemove(obj, prop, key, val){ return obj[ (isUndef(val) ? "remove" : "set") + prop ](key, val); }
function setRemoveNS(obj, prop, key, val, ns= null){ return obj[ (isUndef(val) ? "remove" : "set") + prop + "NS" ](ns, key, val); } function setRemoveNS(obj, prop, key, val, ns= null){ return obj[ (isUndef(val) ? "remove" : "set") + prop + "NS" ](ns, key, val); }
function setDelete(obj, prop, val){ return Reflect.set(obj, prop, val); }

View File

@ -1,3 +1,4 @@
export function isUndef(value){ return typeof value==="undefined"; }
export function typeOf(v){ export function typeOf(v){
const t= typeof v; const t= typeof v;
if(t!=="object") return t; if(t!=="object") return t;

View File

@ -1,3 +1,11 @@
import { prop_process } from './dom-common.js';
const { setDelete }= prop_process;
/** @param {HTMLElement} obj */
prop_process.setDelete= function(obj, prop, value){
if("checked"!==prop) return setDelete(obj, prop, value);
if(value) return obj.setAttribute("checked", "");
obj.removeAttribute("checked");
}
const keys= [ "HTMLElement", "SVGElement", "DocumentFragment", "MutationObserver", "document" ]; const keys= [ "HTMLElement", "SVGElement", "DocumentFragment", "MutationObserver", "document" ];
let dom_last; let dom_last;
export let el; export let el;

View File

@ -1,6 +1,5 @@
import { typeOf } from './helpers.js';
export const signals_global= { export const signals_global= {
isTextContent(attributes){ return typeOf(attributes)!=="[object Object]"; }, isTextContent(attributes){ return typeof attributes==="string"; },
processReactiveAttribute(el, key, attr, assignNth){ return attr; }, processReactiveAttribute(el, key, attr, assignNth){ return attr; },
}; };
export function registerReactivity(def, global= true){ export function registerReactivity(def, global= true){

View File

@ -25,6 +25,7 @@ export class CustomHTMLTestElement extends HTMLElement{
); );
} }
} }
// https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4
customElementsAssign( customElementsAssign(
CustomHTMLTestElement, CustomHTMLTestElement,
reflectObservedAttributes, reflectObservedAttributes,

View File

@ -12,7 +12,12 @@
<script type="module"> <script type="module">
import { el } from "../index.js"; import { el } from "../index.js";
document.body.append( document.body.append(
el("p", { textContent: "Ahoj", style: { color: "green" } }) el("input", { type: "checkbox", name: "name", checked: true, id: undefined }),
el("p", { textContent: "Ahoj", style: { color: "green" } }),
el("select", { value: "a" }).append(
el("option", { value: "a", textContent: "A" }),
el("option", { value: "b", textContent: "B" })
)
); );
</script> </script>
</head> </head>