1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-09-17 17:59:45 +00:00
TiddlyWiki5/core/modules/rendertree/renderers/widget.js
Jeremy Ruston 6ccf13e624 Widgets and macro calls should be spans not divs
Although it does mean that we'll end up creating divs inside spans,
which isn't strictly legal but works in all browsers
2012-12-20 10:37:51 +00:00

133 lines
3.6 KiB
JavaScript

/*\
title: $:/core/modules/rendertree/renderers/widget.js
type: application/javascript
module-type: wikirenderer
Widget renderer.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Widget renderer
*/
var WidgetRenderer = function(renderTree,renderContext,parseTreeNode) {
// Store state information
this.renderTree = renderTree;
this.renderContext = renderContext;
this.parseTreeNode = parseTreeNode;
// Compute our attributes
this.attributes = {};
this.computeAttributes();
// Create the widget object
var WidgetClass = this.renderTree.parser.vocabulary.widgetClasses[this.parseTreeNode.tag];
if(WidgetClass) {
this.widget = new WidgetClass();
this.widget.init(this);
} else {
// Error if we couldn't find the widget
this.children = this.renderTree.createRenderers(this.renderContext,[
{type: "text", text: "Unknown widget type '" + this.parseTreeNode.tag + "'"}
]);
}
};
WidgetRenderer.prototype.computeAttributes = function() {
var changedAttributes = {};
var self = this;
$tw.utils.each(this.parseTreeNode.attributes,function(attribute,name) {
if(attribute.type === "indirect") {
var value = self.renderTree.wiki.getTextReference(attribute.textReference,self.renderContext.tiddlerTitle);
if(self.attributes[name] !== value) {
self.attributes[name] = value;
changedAttributes[name] = true;
}
} else { // String attribute
if(self.attributes[name] !== attribute.value) {
self.attributes[name] = attribute.value;
changedAttributes[name] = true;
}
}
});
return changedAttributes;
};
WidgetRenderer.prototype.hasAttribute = function(name) {
return $tw.utils.hop(this.attributes,name);
};
WidgetRenderer.prototype.getAttribute = function(name,defaultValue) {
if($tw.utils.hop(this.attributes,name)) {
return this.attributes[name];
} else {
return defaultValue;
}
};
WidgetRenderer.prototype.render = function(type) {
// Render the widget if we've got one
if(this.widget && this.widget.render) {
return this.widget.render(type);
}
};
WidgetRenderer.prototype.renderInDom = function() {
// Create the wrapper element
this.domNode = document.createElement("span");
this.domNode.setAttribute("data-widget-type",this.parseTreeNode.tag);
this.domNode.setAttribute("data-widget-attr",JSON.stringify(this.attributes));
// Render the widget if we've got one
if(this.widget) {
this.widget.renderInDom(this.domNode);
// Attach any event handlers
if(this.widget.getEventListeners) {
$tw.utils.addEventListeners(this.domNode,this.widget.getEventListeners());
}
}
// Return the dom node
return this.domNode;
};
WidgetRenderer.prototype.refreshInDom = function(changedTiddlers) {
// Update our attributes
var changedAttributes = this.computeAttributes();
// Refresh the widget
if(this.widget && this.widget.refreshInDom) {
this.widget.refreshInDom(changedAttributes,changedTiddlers);
}
};
WidgetRenderer.prototype.getContextTiddlerTitle = function() {
return this.renderContext ? this.renderContext.tiddlerTitle : undefined;
};
/*
Check for render context recursion by returning true if the members of a proposed new render context are already present in the render context chain
*/
WidgetRenderer.prototype.checkContextRecursion = function(newRenderContext) {
var context = this.renderContext;
while(context) {
var match = true;
for(var member in newRenderContext) {
if($tw.utils.hop(newRenderContext,member)) {
if(newRenderContext[member] && newRenderContext[member] !== context[member]) {
match = false;
}
}
}
if(match) {
return true;
}
context = context.parentContext;
}
return false;
};
exports.widget = WidgetRenderer
})();