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

♻️ split assign to assign and assignAttribute

This commit is contained in:
Jan Andrle 2023-10-15 11:12:06 +02:00
parent 7d4cc29174
commit f08d495a5c
Signed by: jaandrle
GPG Key ID: B3A25AED155AFFAB
3 changed files with 48 additions and 36 deletions

View File

@ -69,42 +69,54 @@ export { createElement as el };
import { prop_process } from './dom-common.js';
const { setDeleteAttr }= prop_process;
const assign_context= new WeakMap();
export function assign(element, ...attributes){
const _this= this;
const s= signals(this);
if(!attributes.length) return element;
assign_context.set(element, assignContext(element, this));
for(const [ key, value ] of Object.entries(Object.assign({}, ...attributes)))
assignAttribute.call(this, element, key, value);
assign_context.delete(element);
return element;
}
export function assignAttribute(element, key, value){
/* jshint maxcomplexity:14 */
const { setRemoveAttr, s }= assignContext(element, this);
const _this= this;
value= s.processReactiveAttribute(element, key, value,
(key, value)=> assignAttribute.call(_this, element, key, value));
const [ k ]= key;
if("="===k) return setRemoveAttr(key.slice(1), value);
if("."===k) return setDelete(element, key.slice(1), value);
if(/(aria|data)([A-Z])/.test(key)){//TODO: temporal as aria* exists in Element for some browsers
key= key.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
return setRemoveAttr(key, value);
}
if("className"===key) key= "class";//just optimalization, `isPropSetter` returns false immediately
switch(key){
case "xlink:href":
return setRemoveAttr(key, value, "http://www.w3.org/1999/xlink");
case "textContent": //just optimalization, its part of Node ⇒ deep for `isPropSetter`
return setDeleteAttr(element, key, value);
case "style":
if(typeof value!=="object") break;
/* falls through */
case "dataset":
return forEachEntries(s, value, setDelete.bind(null, element[key]));
case "ariaset":
return forEachEntries(s, value, (key, val)=> setRemoveAttr("aria-"+key, val));
case "classList":
return classListDeclarative.call(_this, element, value);
}
return isPropSetter(element, key) ? setDeleteAttr(element, key, value) : setRemoveAttr(key, value);
}
function assignContext(element, _this){
if(assign_context.has(element)) return assign_context.get(element);
const is_svg= element instanceof SVGElement;
const setRemoveAttr= (is_svg ? setRemoveNS : setRemove).bind(null, element, "Attribute");
/* jshint maxcomplexity:13 */
Object.entries(Object.assign({}, ...attributes)).forEach(function assignNth([ key, attr ]){
attr= s.processReactiveAttribute(element, key, attr, assignNth);
const [ k ]= key;
if("="===k) return setRemoveAttr(key.slice(1), attr);
if("."===k) return setDelete(element, key.slice(1), attr);
if(/(aria|data)([A-Z])/.test(key)){//TODO: temporal as aria* exists in Element for some browsers
key= key.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
return setRemoveAttr(key, attr);
}
if("className"===key) key= "class";//just optimalization, `isPropSetter` returns false immediately
switch(key){
case "xlink:href":
return setRemoveAttr(key, attr, "http://www.w3.org/1999/xlink");
case "textContent": //just optimalization, its part of Node ⇒ deep for `isPropSetter`
return setDeleteAttr(element, key, attr);
case "style":
if(typeof attr!=="object") break;
/* falls through */
case "dataset":
return forEachEntries(s, attr, setDelete.bind(null, element[key]));
case "ariaset":
return forEachEntries(s, attr, (key, val)=> setRemoveAttr("aria-"+key, val));
case "classList":
return classListDeclarative.call(_this, element, attr);
}
return isPropSetter(element, key) ? setDeleteAttr(element, key, attr) : setRemoveAttr(key, attr);
});
return element;
const s= signals(_this);
return { setRemoveAttr, s };
}
export function classListDeclarative(element, toggle){
const s= signals(this);
@ -137,7 +149,7 @@ function forEachEntries(s, obj, cb){
if(typeof obj !== "object" || obj===null) return;
return Object.entries(obj).forEach(function process([ key, val ]){
if(!key) return;
val= s.processReactiveAttribute(obj, key, val, a=> cb(...a));
val= s.processReactiveAttribute(obj, key, val, cb);
cb(key, val);
});
}

View File

@ -1,6 +1,6 @@
export const signals_global= {
isSignal(attributes){ return false; },
processReactiveAttribute(obj, key, attr, assignNth){ return attr; },
processReactiveAttribute(obj, key, attr, set){ return attr; },
};
export function registerReactivity(def, global= true){
if(global) return Object.assign(signals_global, def);

View File

@ -107,9 +107,9 @@ S.el= function(signal, map){
import { typeOf } from './helpers.js';
export const signals_config= {
isSignal,
processReactiveAttribute(_, key, attrs, assignNth){
processReactiveAttribute(_, key, attrs, set){
if(!isSignal(attrs)) return attrs;
const l= attr=> assignNth([ key, attr ]);
const l= attr=> set(key, attr);
addSignalListener(attrs, l);
removeSignalsFromElements(attrs, l, _, key);
return attrs();