mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-27 03:57:21 +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:
parent
35a842ade6
commit
bd2cf5c464
@ -29,45 +29,47 @@ Render this widget into the DOM
|
||||
ElementWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
// Neuter blacklisted elements
|
||||
var tag = this.parseTreeNode.tag;
|
||||
if($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {
|
||||
tag = "safe-" + tag;
|
||||
this.tag = this.parseTreeNode.tag;
|
||||
if($tw.config.htmlUnsafeElements.indexOf(this.tag) !== -1) {
|
||||
this.tag = "safe-" + this.tag;
|
||||
}
|
||||
// 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) {
|
||||
var baseLevel = parseInt(this.getVariable("tv-adjust-heading-level","0"),10) || 0;
|
||||
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
|
||||
var tagNamespaces = {
|
||||
svg: "http://www.w3.org/2000/svg",
|
||||
math: "http://www.w3.org/1998/Math/MathML",
|
||||
body: "http://www.w3.org/1999/xhtml"
|
||||
};
|
||||
this.namespace = tagNamespaces[this.parseTreeNode.tag];
|
||||
this.namespace = tagNamespaces[this.tag];
|
||||
if(this.namespace) {
|
||||
this.setVariable("namespace",this.namespace);
|
||||
} else {
|
||||
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
|
||||
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(),
|
||||
hasChangedAttributes = $tw.utils.count(changedAttributes) > 0;
|
||||
if(hasChangedAttributes) {
|
||||
// Update our attributes
|
||||
this.assignAttributes(this.domNodes[0],{excludeEventAttributes: true});
|
||||
if(!this.isReplaced) {
|
||||
// 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;
|
||||
};
|
||||
|
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;
|
||||
});
|
||||
```
|
Loading…
Reference in New Issue
Block a user