241 lines
6.7 KiB
TypeScript
241 lines
6.7 KiB
TypeScript
import { IncrementalIDGenerator } from "../random/IncrementalIDGenerator";
|
|
import { ElementAttribute } from "../dom/ElementAttribute";
|
|
import { TemplateReplacer } from "./TemplateReplacer";
|
|
import { ElementProcessor } from "./ElementProcessor";
|
|
import { DOMEditor as HTMLEditor } from "../dom/DOMEditor";
|
|
import { StylesProcessor } from "./styles-processor/StylesProcessor";
|
|
import { ElementType } from "../dom/ElementType";
|
|
|
|
|
|
export enum TemplatesManagerMode
|
|
{
|
|
ADD_STYLES_TO_HEAD,
|
|
IGNORE_STYLES
|
|
}
|
|
|
|
export class TemplatesManager
|
|
{
|
|
static readonly defaultOverloadAttributeName = "templates-overload-type";
|
|
static readonly defaultIDAttributeName = "templates-id";
|
|
static readonly id = new ElementAttribute( TemplatesManager.defaultIDAttributeName );
|
|
|
|
private _overloadAttribute = new ElementAttribute( TemplatesManager.defaultOverloadAttributeName );
|
|
private _idAttribute = new ElementAttribute( TemplatesManager.defaultIDAttributeName );
|
|
|
|
private _templatesMap:Map<string,Element> = new Map<string,Element>();
|
|
private _idGenerator:IncrementalIDGenerator = new IncrementalIDGenerator();
|
|
private _replacer:TemplateReplacer = new TemplateReplacer();
|
|
get replacer(){ return this._replacer; }
|
|
private _mode = TemplatesManagerMode.ADD_STYLES_TO_HEAD;
|
|
private _templateStyles:string[] = [];
|
|
private _additionalProcessor = new Map<string,ElementProcessor>();
|
|
|
|
setMode( mode:TemplatesManagerMode )
|
|
{
|
|
this._mode = mode;
|
|
}
|
|
|
|
addProcessor( processor:ElementProcessor )
|
|
{
|
|
this._additionalProcessor.set( processor.getElementName(), processor );
|
|
}
|
|
|
|
addTemplate( element:Element )
|
|
{
|
|
|
|
if ( Node.ELEMENT_NODE !== element.nodeType )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( "STYLE" === element.nodeName.toUpperCase() )
|
|
{
|
|
this._addStyle( element );
|
|
return;
|
|
}
|
|
|
|
let hash = element.nodeName;
|
|
|
|
if ( this._overloadAttribute.in( element ) )
|
|
{
|
|
let overloadType = this._overloadAttribute.from( element );
|
|
hash += " " + overloadType;
|
|
}
|
|
|
|
this._templatesMap.set( hash, element );
|
|
}
|
|
|
|
static templateIDCounter = 0;
|
|
addTemplateHTML( html:string )
|
|
{
|
|
TemplatesManager.templateIDCounter ++;
|
|
|
|
let generatedDocument = HTMLEditor.stringToDocument( `<html><body>${html}</body>` );
|
|
|
|
let children = HTMLEditor.nodeListToArray( generatedDocument.body.childNodes );
|
|
|
|
for ( let i = 0; i < children.length; i++ )
|
|
{
|
|
this.addTemplate( children[ i ] );
|
|
}
|
|
}
|
|
|
|
|
|
processChildren( root:Element )
|
|
{
|
|
let children = HTMLEditor.nodeListToArray( root.childNodes );
|
|
|
|
for ( let i = 0; i < children.length; i++ )
|
|
{
|
|
this._processElement( children[ i ] );
|
|
}
|
|
}
|
|
|
|
processElement( element:Element )
|
|
{
|
|
return this._processElement( element );
|
|
}
|
|
|
|
getTemplate( nodeName:string )
|
|
{
|
|
return this._templatesMap.get( nodeName.toUpperCase() );
|
|
}
|
|
|
|
createTemplate( nodeName:string, doc:Document = undefined )
|
|
{
|
|
doc = doc || document;
|
|
|
|
let templateNode = doc.importNode( this.getTemplate( nodeName ), true );
|
|
templateNode = this._processElement( templateNode );
|
|
|
|
return templateNode;
|
|
}
|
|
|
|
private _addStyle( styleElement:Element )
|
|
{
|
|
if ( TemplatesManagerMode.IGNORE_STYLES === this._mode )
|
|
{
|
|
//this._templateStyles.push( styleElement.innerHTML );
|
|
//console.log( "Adding style to templates.css", styleElement );
|
|
return;
|
|
}
|
|
|
|
let styleContent = styleElement.textContent;
|
|
let processedStyleContent = StylesProcessor.convert( styleContent );
|
|
let clonedStyle = ElementType.style.create();
|
|
clonedStyle.innerHTML = processedStyleContent;
|
|
//let clonedStyle = document.importNode( styleElement, true );
|
|
document.head.appendChild( clonedStyle );
|
|
|
|
let id = this._idGenerator.createID();
|
|
this._idAttribute.to( styleElement, id );
|
|
this._idAttribute.to( clonedStyle, id );
|
|
|
|
//console.log( "Adding style to head", styleElement, clonedStyle );
|
|
}
|
|
|
|
private _processElement( element:Element ):Element
|
|
{
|
|
//console.log( "Processing:", HierarchyName.of( element ) );
|
|
|
|
if ( this._idAttribute.in( element ) )
|
|
{
|
|
this.processChildren( element );
|
|
return element;
|
|
}
|
|
|
|
if ( this._additionalProcessor.has( element.nodeName ) )
|
|
{
|
|
let processor = this._additionalProcessor.get( element.nodeName );
|
|
let processedElement:Element = null;
|
|
|
|
//console.log( "ADDITIONAL PROCESSOR", processor );
|
|
try
|
|
{
|
|
processedElement = processor.processElement( element );
|
|
}
|
|
catch ( e )
|
|
{
|
|
console.log( "Processor:", processor, `ERROR: in <${element.nodeName.toLowerCase()}>` );
|
|
throw e;
|
|
}
|
|
|
|
this._idAttribute.to( processedElement, this._idGenerator.createID() );
|
|
//console.log( "Replacing Kids:", HierarchyName.of( processedElement ) );
|
|
|
|
this._replacer.replaceChildren( element, processedElement );
|
|
|
|
//console.log( "PROCESSING Kids:", HierarchyName.of( processedElement ) );
|
|
this.processChildren( processedElement );
|
|
|
|
if ( processor.hasPostProcessor )
|
|
{
|
|
processor.postProcessElement( element, processedElement );
|
|
}
|
|
|
|
|
|
return processedElement;
|
|
}
|
|
|
|
if ( ! this._templatesMap.has( element.nodeName ) )
|
|
{
|
|
this.processChildren( element );
|
|
return element;
|
|
}
|
|
|
|
let classElement = this._templatesMap.get( element.nodeName.toUpperCase() );
|
|
|
|
let replacedElement:Element = null;
|
|
|
|
try
|
|
{
|
|
replacedElement = this._replacer.replace( element, classElement );
|
|
}
|
|
catch ( e )
|
|
{
|
|
console.log( `Replacer-Error: in <${element.nodeName.toLowerCase()}>`, e.stack );
|
|
throw e;
|
|
}
|
|
|
|
|
|
|
|
//console.log( "CLASS ELEMENT", classElement, replacedElement );
|
|
this._idAttribute.to( replacedElement, this._idGenerator.createID() );
|
|
|
|
this.processChildren( replacedElement );
|
|
|
|
return replacedElement;
|
|
|
|
}
|
|
|
|
static addCustomElements()
|
|
{
|
|
let customElementsManager = new TemplatesManager();
|
|
|
|
let customElements = document.querySelector( "custom-elements" );
|
|
|
|
if ( ! customElements )
|
|
{
|
|
return;
|
|
}
|
|
|
|
let customElementsNodes = customElements.childNodes;
|
|
|
|
|
|
for ( let i = 0; i < customElementsNodes.length; i++ )
|
|
{
|
|
if ( Node.ELEMENT_NODE != customElementsNodes[ i ].nodeType )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//console.log( customElementsNodes[ i ].nodeName );
|
|
|
|
customElementsManager.addTemplate( customElementsNodes[ i ] as Element);
|
|
}
|
|
|
|
HTMLEditor.remove( customElements );
|
|
|
|
customElementsManager.processChildren( document.body );
|
|
}
|
|
} |