lupine.web
Version:
lupine.web is a extremely fast, small size and lightweight frontend framework, using React TSX syntax.
94 lines (84 loc) • 3.6 kB
text/typescript
import { VNode } from '../jsx';
import { replaceInnerhtml, replaceBetweenComments } from './replace-innerhtml';
import { MounterProps } from '../models/mounter-props';
export const bindRef = (type: any, newProps: any, el: Element | Node, mounters: MounterProps) => {
// console.log('========', newProps, el);
const id = newProps.id || newProps._id;
// newProps["ref"].id = id; // this is set at bindAttributes
(el as any)._lj = (el as any)._lj || {};
(el as any)._lj.ref = newProps['ref'];
newProps['ref'].current = el;
if (newProps['ref'].onLoad) {
// setTimeout(() => newProps['ref'].onLoad(el), 0);
// Promise.resolve().then(fn) will be called in the end of current event loop (quicker than setTimeout)
const defer = Promise.prototype.then.bind(Promise.resolve());
defer(() => newProps['ref'].onLoad(el));
}
if (newProps['ref'].onUnload) {
(el as any)._lj.onUnload = async () => {
await newProps['ref'].onUnload(el);
};
}
/**
* ref.$('selector')
* @param selector
* @returns Element
*/
newProps['ref'].$ = (selector: string) => {
if (!selector || selector === '&') return el;
if (el.nodeType === 8) {
console.warn('Cannot use querySelector on a Comment node');
return null;
}
if (newProps['ref'].referToCssId) {
const gId = newProps['ref'].referToCssId;
if (selector.startsWith('&')) {
// top node may not have the gId classname
return (el as Element).querySelector(`.${id}${selector.substring(1).replace(/&/g, gId)}`);
}
return (el as Element).querySelector(selector.replace(/&/g, gId));
}
if (selector.startsWith('&')) {
return (el as Element).querySelector(`.${id}${selector.substring(1).replace(/&/g, id)}`);
}
return (el as Element).querySelector(selector.replace(/&/g, id));
};
newProps['ref'].$all = (selector: string) => {
if (!selector || selector === '&') return [el];
if (el.nodeType === 8) {
console.warn('Cannot use querySelectorAll on a Comment node');
return [];
}
if (newProps['ref'].referToCssId) {
const gId = newProps['ref'].referToCssId;
if (selector.startsWith('&')) {
// top node may not have the gId classname
return (el as Element).querySelectorAll(`.${id}${selector.substring(1).replace(/&/g, gId)}`);
}
return (el as Element).querySelectorAll(selector.replace(/&/g, gId));
}
if (selector.startsWith('&')) {
return (el as Element).querySelectorAll(`.${id}${selector.substring(1).replace(/&/g, id)}`);
}
return (el as Element).querySelectorAll(selector.replace(/&/g, id));
};
newProps['ref'].mountInnerComponent = async (content: string | VNode<any>) => {
if (typeof content === 'object' && content.type && content.props) {
mounters.mountInnerComponent && await mounters.mountInnerComponent(el as Element, content);
} else {
if (el.nodeType === 8) {
await replaceBetweenComments(el as Comment, content as string);
} else {
await replaceInnerhtml(el as Element, content as string);
}
}
};
newProps['ref'].mountOuterComponent = async (content: VNode<any>) => {
mounters.mountOuterComponent && await mounters.mountOuterComponent(el as Element, content);
};
if (!newProps['ref'].refresh) {
newProps['ref'].refresh = async () => {
console.warn('refresh() not available: This ref is not attached to a functional component root.');
};
}
};