mirror of
https://github.com/TiddlyWiki/TiddlyWiki5.git
synced 2026-05-05 07:46:54 +00:00
Fixed up the D3 demo plugin
This commit is contained in:
184
plugins/tiddlywiki/d3/cloudwidget.js
vendored
184
plugins/tiddlywiki/d3/cloudwidget.js
vendored
@@ -1,7 +1,7 @@
|
||||
/*\
|
||||
title: $:/plugins/tiddlywiki/d3/cloudwidget.js
|
||||
type: application/javascript
|
||||
module-type: widget
|
||||
module-type: new_widget
|
||||
|
||||
A widget for displaying word clouds. Derived from https://github.com/jasondavies/d3-cloud
|
||||
|
||||
@@ -12,7 +12,8 @@ A widget for displaying word clouds. Derived from https://github.com/jasondavies
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var d3 = require("$:/plugins/tiddlywiki/d3/d3.js").d3;
|
||||
var Widget = require("$:/core/modules/new_widgets/widget.js").widget,
|
||||
d3 = require("$:/plugins/tiddlywiki/d3/d3.js").d3;
|
||||
|
||||
if($tw.browser) {
|
||||
// Frightful hack to give the cloud plugin the global d3 variable it needs
|
||||
@@ -20,98 +21,121 @@ if($tw.browser) {
|
||||
d3.layout.cloud = require("$:/plugins/tiddlywiki/d3/d3.layout.cloud.js").cloud;
|
||||
}
|
||||
|
||||
var CloudWidget = function(renderer) {
|
||||
// Save state
|
||||
this.renderer = renderer;
|
||||
// Generate child nodes
|
||||
this.generate();
|
||||
var CloudWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
|
||||
CloudWidget.prototype.generate = function() {
|
||||
// Get the parameters
|
||||
this.data = this.renderer.getAttribute("data");
|
||||
this.spiral = this.renderer.getAttribute("spiral","archimedean");
|
||||
// Set the return element
|
||||
this.tag = "div";
|
||||
this.attributes = {
|
||||
"class": "tw-cloudwidget"
|
||||
/*
|
||||
Inherit from the base widget class
|
||||
*/
|
||||
CloudWidget.prototype = new Widget();
|
||||
|
||||
/*
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
CloudWidget.prototype.render = function(parent,nextSibling) {
|
||||
// Save the parent dom node
|
||||
this.parentDomNode = parent;
|
||||
// Compute our attributes
|
||||
this.computeAttributes();
|
||||
// Execute our logic
|
||||
this.execute();
|
||||
// Create the chart
|
||||
var chart = this.createChart(parent,nextSibling);
|
||||
this.updateChart = chart.updateChart;
|
||||
if(this.updateChart) {
|
||||
this.updateChart();
|
||||
}
|
||||
// Insert the chart into the DOM and render any children
|
||||
parent.insertBefore(chart.domNode,nextSibling);
|
||||
this.domNodes.push(chart.domNode);
|
||||
};
|
||||
|
||||
CloudWidget.prototype.createChart = function(parent,nextSibling) {
|
||||
var self = this,
|
||||
fill = d3.scale.category20(),
|
||||
data = this.wiki.getTiddlerData(this.cloudData);
|
||||
// Use dummy data if none provided
|
||||
if(!data) {
|
||||
data = "This word cloud does not have any data in it".split(" ").map(function(d) {
|
||||
return {text: d, size: 10 + Math.random() * 90};
|
||||
});
|
||||
}
|
||||
// Create the svg element
|
||||
var svgElement = d3.select(parent).insert("svg",nextSibling)
|
||||
.attr("width", 600)
|
||||
.attr("height", 400);
|
||||
// Create the main group
|
||||
var mainGroup = svgElement
|
||||
.append("g")
|
||||
.attr("transform", "translate(300,200)");
|
||||
// Create the layout
|
||||
var layout = d3.layout.cloud().size([600, 400])
|
||||
.words(data)
|
||||
.padding(5)
|
||||
.rotate(function() { return ~~(Math.random() * 5) * 30 - 60; })
|
||||
.font("Impact")
|
||||
.fontSize(function(d) { return d.size*2; })
|
||||
.on("end", draw)
|
||||
.start();
|
||||
// Function to draw all the words
|
||||
function draw(words) {
|
||||
mainGroup.selectAll("text")
|
||||
.data(words)
|
||||
.enter().append("text")
|
||||
.style("font-size", function(d) { return d.size + "px"; })
|
||||
.style("font-family", "Impact")
|
||||
.style("fill", function(d, i) { return fill(i); })
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("transform", function(d) {
|
||||
return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
|
||||
})
|
||||
.text(function(d) { return d.text; });
|
||||
}
|
||||
function updateChart() {
|
||||
layout.spiral(self.spiral);
|
||||
}
|
||||
return {
|
||||
domNode: svgElement[0][0],
|
||||
updateChart: updateChart
|
||||
};
|
||||
};
|
||||
|
||||
CloudWidget.prototype.postRenderInDom = function() {
|
||||
this.updateChart = this.createChart();
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
CloudWidget.prototype.execute = function() {
|
||||
// Get the parameters from the attributes
|
||||
this.cloudData = this.getAttribute("data");
|
||||
this.cloudSpiral = this.getAttribute("spiral","archimedean");
|
||||
};
|
||||
|
||||
CloudWidget.prototype.refreshInDom = function(changedAttributes,changedTiddlers) {
|
||||
// Reexecute the widget if the data reference attributes have changed
|
||||
if(changedAttributes.data || changedTiddlers[this.data]) {
|
||||
// Regenerate and rerender the widget and replace the existing DOM node
|
||||
this.generate();
|
||||
var oldDomNode = this.renderer.domNode,
|
||||
newDomNode = this.renderer.renderInDom();
|
||||
oldDomNode.parentNode.replaceChild(newDomNode,oldDomNode);
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
CloudWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if(changedAttributes.data || changedTiddlers[this.cloudData]) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else if(changedAttributes.spiral) {
|
||||
// Update the chart if the spiral setting has changed
|
||||
this.spiral = this.renderer.getAttribute("spiral","archimedean");
|
||||
this.execute();
|
||||
if(this.updateChart) {
|
||||
this.updateChart();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
CloudWidget.prototype.createChart = function() {
|
||||
|
||||
var self = this;
|
||||
|
||||
var domNode = this.renderer.domNode;
|
||||
|
||||
var fill = d3.scale.category20();
|
||||
|
||||
|
||||
var data = this.renderer.renderTree.wiki.getTiddlerData(this.data);
|
||||
|
||||
if(!data) {
|
||||
// Use dummy data if none provided
|
||||
data = "This word cloud does not have any data in it".split(" ").map(function(d) {
|
||||
return {text: d, size: 10 + Math.random() * 90};
|
||||
})
|
||||
}
|
||||
|
||||
var svg = d3.select(domNode).append("svg")
|
||||
.attr("width", 600)
|
||||
.attr("height", 400)
|
||||
.append("g")
|
||||
.attr("transform", "translate(300,200)");
|
||||
|
||||
var layout = d3.layout.cloud().size([600, 400])
|
||||
.words(data)
|
||||
.padding(5)
|
||||
.rotate(function() { return ~~(Math.random() * 5) * 30 - 60; })
|
||||
.font("Impact")
|
||||
.fontSize(function(d) { return d.size*2; })
|
||||
.on("end", draw)
|
||||
.start();
|
||||
|
||||
function draw(words) {
|
||||
svg.selectAll("text")
|
||||
.data(words)
|
||||
.enter().append("text")
|
||||
.style("font-size", function(d) { return d.size + "px"; })
|
||||
.style("font-family", "Impact")
|
||||
.style("fill", function(d, i) { return fill(i); })
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("transform", function(d) {
|
||||
return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
|
||||
})
|
||||
.text(function(d) { return d.text; });
|
||||
}
|
||||
|
||||
function updateChart() {
|
||||
layout.spiral(self.spiral);
|
||||
}
|
||||
|
||||
return updateChart;
|
||||
|
||||
/*
|
||||
Remove any DOM nodes created by this widget or its children
|
||||
*/
|
||||
CloudWidget.prototype.removeChildDomNodes = function() {
|
||||
$tw.utils.each(this.domNodes,function(domNode) {
|
||||
domNode.parentNode.removeChild(domNode);
|
||||
});
|
||||
this.domNodes = [];
|
||||
};
|
||||
|
||||
exports.d3cloud = CloudWidget;
|
||||
|
||||
Reference in New Issue
Block a user