mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-09-10 23:06:06 +00:00
Extend the element widget with a hook to intercept DOM node creation
The element widget is used to render HTML elements in wikitext.
This commit is contained in:
@@ -29,45 +29,47 @@ Render this widget into the DOM
|
|||||||
ElementWidget.prototype.render = function(parent,nextSibling) {
|
ElementWidget.prototype.render = function(parent,nextSibling) {
|
||||||
this.parentDomNode = parent;
|
this.parentDomNode = parent;
|
||||||
this.computeAttributes();
|
this.computeAttributes();
|
||||||
this.execute();
|
|
||||||
// Neuter blacklisted elements
|
// Neuter blacklisted elements
|
||||||
var tag = this.parseTreeNode.tag;
|
this.tag = this.parseTreeNode.tag;
|
||||||
if($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {
|
if($tw.config.htmlUnsafeElements.indexOf(this.tag) !== -1) {
|
||||||
tag = "safe-" + tag;
|
this.tag = "safe-" + this.tag;
|
||||||
}
|
}
|
||||||
// Adjust headings by the current base level
|
// Adjust headings by the current base level
|
||||||
var headingLevel = ["h1","h2","h3","h4","h5","h6"].indexOf(tag);
|
var headingLevel = ["h1","h2","h3","h4","h5","h6"].indexOf(this.tag);
|
||||||
if(headingLevel !== -1) {
|
if(headingLevel !== -1) {
|
||||||
var baseLevel = parseInt(this.getVariable("tv-adjust-heading-level","0"),10) || 0;
|
var baseLevel = parseInt(this.getVariable("tv-adjust-heading-level","0"),10) || 0;
|
||||||
headingLevel = Math.min(Math.max(headingLevel + 1 + baseLevel,1),6);
|
headingLevel = Math.min(Math.max(headingLevel + 1 + baseLevel,1),6);
|
||||||
tag = "h" + headingLevel;
|
this.tag = "h" + headingLevel;
|
||||||
}
|
}
|
||||||
// Create the DOM node
|
|
||||||
var domNode = this.document.createElementNS(this.namespace,tag);
|
|
||||||
this.assignAttributes(domNode,{excludeEventAttributes: true});
|
|
||||||
parent.insertBefore(domNode,nextSibling);
|
|
||||||
this.renderChildren(domNode,null);
|
|
||||||
this.domNodes.push(domNode);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Compute the internal state of the widget
|
|
||||||
*/
|
|
||||||
ElementWidget.prototype.execute = function() {
|
|
||||||
// Select the namespace for the tag
|
// Select the namespace for the tag
|
||||||
var tagNamespaces = {
|
var tagNamespaces = {
|
||||||
svg: "http://www.w3.org/2000/svg",
|
svg: "http://www.w3.org/2000/svg",
|
||||||
math: "http://www.w3.org/1998/Math/MathML",
|
math: "http://www.w3.org/1998/Math/MathML",
|
||||||
body: "http://www.w3.org/1999/xhtml"
|
body: "http://www.w3.org/1999/xhtml"
|
||||||
};
|
};
|
||||||
this.namespace = tagNamespaces[this.parseTreeNode.tag];
|
this.namespace = tagNamespaces[this.tag];
|
||||||
if(this.namespace) {
|
if(this.namespace) {
|
||||||
this.setVariable("namespace",this.namespace);
|
this.setVariable("namespace",this.namespace);
|
||||||
} else {
|
} else {
|
||||||
this.namespace = this.getVariable("namespace",{defaultValue: "http://www.w3.org/1999/xhtml"});
|
this.namespace = this.getVariable("namespace",{defaultValue: "http://www.w3.org/1999/xhtml"});
|
||||||
}
|
}
|
||||||
|
// Invoke the th-rendering-element hook
|
||||||
|
var parseTreeNodes = $tw.hooks.invokeHook("th-rendering-element",null,this);
|
||||||
|
this.isReplaced = !!parseTreeNodes;
|
||||||
|
if(parseTreeNodes) {
|
||||||
|
// Use the parse tree nodes provided by the hook
|
||||||
|
this.makeChildWidgets(parseTreeNodes);
|
||||||
|
this.renderChildren(this.parentDomNode,null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Make the child widgets
|
// Make the child widgets
|
||||||
this.makeChildWidgets();
|
this.makeChildWidgets();
|
||||||
|
// Create the DOM node and render children
|
||||||
|
var domNode = this.document.createElementNS(this.namespace,this.tag);
|
||||||
|
this.assignAttributes(domNode,{excludeEventAttributes: true});
|
||||||
|
parent.insertBefore(domNode,nextSibling);
|
||||||
|
this.renderChildren(domNode,null);
|
||||||
|
this.domNodes.push(domNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -77,8 +79,13 @@ ElementWidget.prototype.refresh = function(changedTiddlers) {
|
|||||||
var changedAttributes = this.computeAttributes(),
|
var changedAttributes = this.computeAttributes(),
|
||||||
hasChangedAttributes = $tw.utils.count(changedAttributes) > 0;
|
hasChangedAttributes = $tw.utils.count(changedAttributes) > 0;
|
||||||
if(hasChangedAttributes) {
|
if(hasChangedAttributes) {
|
||||||
// Update our attributes
|
if(!this.isReplaced) {
|
||||||
this.assignAttributes(this.domNodes[0],{excludeEventAttributes: true});
|
// Update our attributes
|
||||||
|
this.assignAttributes(this.domNodes[0],{excludeEventAttributes: true});
|
||||||
|
} else {
|
||||||
|
// If we were replaced then completely refresh ourselves
|
||||||
|
return this.refreshSelf();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return this.refreshChildren(changedTiddlers) || hasChangedAttributes;
|
return this.refreshChildren(changedTiddlers) || hasChangedAttributes;
|
||||||
};
|
};
|
||||||
|
35
editions/dev/tiddlers/new/Hook__th-rendering-element.tid
Normal file
35
editions/dev/tiddlers/new/Hook__th-rendering-element.tid
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
created: 20200630121235997
|
||||||
|
modified: 20200630121235997
|
||||||
|
tags: HookMechanism
|
||||||
|
title: Hook: th-rendering-element
|
||||||
|
|
||||||
|
This hook provides a notification that a DOM element is about to be rendered by the "element" widget. The hook can optionally provide an alternate parse tree that will be rendered in place of the intended element.
|
||||||
|
|
||||||
|
Note the element widget only renders those HTML elements that were parsed as plain HTML elements within wikitext (i.e. using the `<tagname>` syntax). This means that this hook is not invoked for elements created by other widgets.
|
||||||
|
|
||||||
|
Hook function parameters:
|
||||||
|
|
||||||
|
* ''newParseTreeNodes'': optional parse tree nodes provided by a previously called hook
|
||||||
|
* ''widget'': instance of the element widget invoking the hook
|
||||||
|
|
||||||
|
Return value:
|
||||||
|
|
||||||
|
* ''newParseTreeNodes'': optionally new parse tree nodes to replace the intended element, or a falsey value to leave the element untouched
|
||||||
|
|
||||||
|
Here is an example of a handler for this hook:
|
||||||
|
|
||||||
|
```js
|
||||||
|
$tw.hooks.addHook("th-rendering-element",function(parseTreeNodes,widget) {
|
||||||
|
// Return the previous mapping if there is one
|
||||||
|
if(parseTreeNodes) {
|
||||||
|
return parseTreeNodes;
|
||||||
|
}
|
||||||
|
// Detect the elements we're interested in
|
||||||
|
if(someCondition()) {
|
||||||
|
// Replace them with a parse tree
|
||||||
|
return generateParseTreeNodes();
|
||||||
|
}
|
||||||
|
// Otherwise do nothing
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
```
|
Reference in New Issue
Block a user