mirror of
				https://github.com/Jermolene/TiddlyWiki5
				synced 2025-11-04 09:33:00 +00:00 
			
		
		
		
	The big purge of the old widget mechanism
Getting rid of the old widget mechanism files finally gives us a payoff for all the refactoring. Still a bit of tidying up to do, and we need to re-introduce the animation mechanisms.
This commit is contained in:
		
							
								
								
									
										6
									
								
								2bld.sh
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								2bld.sh
									
									
									
									
									
								
							@@ -11,7 +11,7 @@ mkdir -p tmp/tw2
 | 
				
			|||||||
node ./tiddlywiki.js \
 | 
					node ./tiddlywiki.js \
 | 
				
			||||||
	editions/tw5.com \
 | 
						editions/tw5.com \
 | 
				
			||||||
	--verbose \
 | 
						--verbose \
 | 
				
			||||||
	--rendertiddler TiddlyWiki2ReadMe editions/tw2/readme.md text/html \
 | 
						--new_rendertiddler TiddlyWiki2ReadMe editions/tw2/readme.md text/html \
 | 
				
			||||||
	|| exit 1
 | 
						|| exit 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# cook the TiddlyWiki 2.x.x index file
 | 
					# cook the TiddlyWiki 2.x.x index file
 | 
				
			||||||
@@ -20,7 +20,7 @@ node ./tiddlywiki.js \
 | 
				
			|||||||
	editions/tw2 \
 | 
						editions/tw2 \
 | 
				
			||||||
	--verbose \
 | 
						--verbose \
 | 
				
			||||||
	--load editions/tw2/source/tiddlywiki.com/index.html.recipe \
 | 
						--load editions/tw2/source/tiddlywiki.com/index.html.recipe \
 | 
				
			||||||
	--rendertiddler $:/core/templates/tiddlywiki2.template.html ./tmp/tw2/index.html text/plain \
 | 
						--new_rendertiddler $:/core/templates/tiddlywiki2.template.html ./tmp/tw2/index.html text/plain \
 | 
				
			||||||
	|| exit 1
 | 
						|| exit 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
opendiff tmp/tw2/index.html editions/tw2/target/index.2.6.5.html
 | 
					diff -q tmp/tw2/index.html editions/tw2/target/prebuilt.html
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										20
									
								
								bld.sh
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								bld.sh
									
									
									
									
									
								
							@@ -35,12 +35,12 @@ rm $TW5_BUILD_OUTPUT/static/*
 | 
				
			|||||||
node ./tiddlywiki.js \
 | 
					node ./tiddlywiki.js \
 | 
				
			||||||
	./editions/tw5.com \
 | 
						./editions/tw5.com \
 | 
				
			||||||
	--verbose \
 | 
						--verbose \
 | 
				
			||||||
	--rendertiddler ReadMe ./readme.md text/html \
 | 
						--new_rendertiddler ReadMe ./readme.md text/html \
 | 
				
			||||||
	--rendertiddler ContributingTemplate ./contributing.md text/html \
 | 
						--new_rendertiddler ContributingTemplate ./contributing.md text/html \
 | 
				
			||||||
	--rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/index.html text/plain \
 | 
						--new_rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/index.html text/plain \
 | 
				
			||||||
	--rendertiddler $:/core/templates/static.template.html $TW5_BUILD_OUTPUT/static.html text/plain \
 | 
						--new_rendertiddler $:/core/templates/static.template.html $TW5_BUILD_OUTPUT/static.html text/plain \
 | 
				
			||||||
	--rendertiddler $:/core/templates/static.template.css $TW5_BUILD_OUTPUT/static/static.css text/plain \
 | 
						--new_rendertiddler $:/core/templates/static.template.css $TW5_BUILD_OUTPUT/static/static.css text/plain \
 | 
				
			||||||
	--rendertiddlers [!is[system]] $:/core/templates/static.tiddler.html $TW5_BUILD_OUTPUT/static text/plain \
 | 
						--new_rendertiddlers [!is[system]] $:/core/templates/static.tiddler.html $TW5_BUILD_OUTPUT/static text/plain \
 | 
				
			||||||
	|| exit 1
 | 
						|| exit 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Second, encrypted.html: a version of the main file encrypted with the password "password"
 | 
					# Second, encrypted.html: a version of the main file encrypted with the password "password"
 | 
				
			||||||
@@ -49,7 +49,7 @@ node ./tiddlywiki.js \
 | 
				
			|||||||
	./editions/tw5.com \
 | 
						./editions/tw5.com \
 | 
				
			||||||
	--verbose \
 | 
						--verbose \
 | 
				
			||||||
	--password password \
 | 
						--password password \
 | 
				
			||||||
	--rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/encrypted.html text/plain \
 | 
						--new_rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/encrypted.html text/plain \
 | 
				
			||||||
	|| exit 1
 | 
						|| exit 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Third, empty.html: empty wiki for reuse
 | 
					# Third, empty.html: empty wiki for reuse
 | 
				
			||||||
@@ -57,7 +57,7 @@ node ./tiddlywiki.js \
 | 
				
			|||||||
node ./tiddlywiki.js \
 | 
					node ./tiddlywiki.js \
 | 
				
			||||||
	./editions/empty \
 | 
						./editions/empty \
 | 
				
			||||||
	--verbose \
 | 
						--verbose \
 | 
				
			||||||
	--rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/empty.html text/plain \
 | 
						--new_rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/empty.html text/plain \
 | 
				
			||||||
	|| exit 1
 | 
						|| exit 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Fourth, tahoelafs.html: empty wiki with plugin for Tahoe-LAFS
 | 
					# Fourth, tahoelafs.html: empty wiki with plugin for Tahoe-LAFS
 | 
				
			||||||
@@ -65,7 +65,7 @@ node ./tiddlywiki.js \
 | 
				
			|||||||
node ./tiddlywiki.js \
 | 
					node ./tiddlywiki.js \
 | 
				
			||||||
	./editions/tahoelafs \
 | 
						./editions/tahoelafs \
 | 
				
			||||||
	--verbose \
 | 
						--verbose \
 | 
				
			||||||
	--rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/tahoelafs.html text/plain \
 | 
						--new_rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/tahoelafs.html text/plain \
 | 
				
			||||||
	|| exit 1
 | 
						|| exit 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Fifth, d3demo.html: wiki to demo d3 plugin
 | 
					# Fifth, d3demo.html: wiki to demo d3 plugin
 | 
				
			||||||
@@ -73,7 +73,7 @@ node ./tiddlywiki.js \
 | 
				
			|||||||
node ./tiddlywiki.js \
 | 
					node ./tiddlywiki.js \
 | 
				
			||||||
	./editions/d3demo \
 | 
						./editions/d3demo \
 | 
				
			||||||
	--verbose \
 | 
						--verbose \
 | 
				
			||||||
	--rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/d3demo.html text/plain \
 | 
						--new_rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/d3demo.html text/plain \
 | 
				
			||||||
	|| exit 1
 | 
						|| exit 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Sixth, run the test edition to run the node.js tests and to generate test.html for tests in the browser
 | 
					# Sixth, run the test edition to run the node.js tests and to generate test.html for tests in the browser
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,44 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/commands/rendertiddler.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: command
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Command to render a tiddler and save it to a file
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.info = {
 | 
					 | 
				
			||||||
	name: "rendertiddler",
 | 
					 | 
				
			||||||
	synchronous: false
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var Command = function(params,commander,callback) {
 | 
					 | 
				
			||||||
	this.params = params;
 | 
					 | 
				
			||||||
	this.commander = commander;
 | 
					 | 
				
			||||||
	this.callback = callback;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Command.prototype.execute = function() {
 | 
					 | 
				
			||||||
	if(this.params.length < 2) {
 | 
					 | 
				
			||||||
		return "Missing filename";
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var self = this,
 | 
					 | 
				
			||||||
		fs = require("fs"),
 | 
					 | 
				
			||||||
		path = require("path"),
 | 
					 | 
				
			||||||
		title = this.params[0],
 | 
					 | 
				
			||||||
		filename = this.params[1],
 | 
					 | 
				
			||||||
		type = this.params[2] || "text/html";
 | 
					 | 
				
			||||||
	fs.writeFile(filename,this.commander.wiki.renderTiddler(type,title),"utf8",function(err) {
 | 
					 | 
				
			||||||
		self.callback(err);
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	return null;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.Command = Command;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,54 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/commands/rendertiddlers.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: command
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Command to render several tiddlers to a folder of files
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.info = {
 | 
					 | 
				
			||||||
	name: "rendertiddlers",
 | 
					 | 
				
			||||||
	synchronous: true
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var Command = function(params,commander,callback) {
 | 
					 | 
				
			||||||
	this.params = params;
 | 
					 | 
				
			||||||
	this.commander = commander;
 | 
					 | 
				
			||||||
	this.callback = callback;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Command.prototype.execute = function() {
 | 
					 | 
				
			||||||
	if(this.params.length < 2) {
 | 
					 | 
				
			||||||
		return "Missing filename";
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var self = this,
 | 
					 | 
				
			||||||
		fs = require("fs"),
 | 
					 | 
				
			||||||
		path = require("path"),
 | 
					 | 
				
			||||||
		wiki = this.commander.wiki,
 | 
					 | 
				
			||||||
		filter = this.params[0],
 | 
					 | 
				
			||||||
		template = this.params[1],
 | 
					 | 
				
			||||||
		pathname = this.params[2],
 | 
					 | 
				
			||||||
		type = this.params[3] || "text/html",
 | 
					 | 
				
			||||||
		extension = this.params[4] || ".html",
 | 
					 | 
				
			||||||
		parser = wiki.parseTiddler(template),
 | 
					 | 
				
			||||||
		tiddlers = wiki.filterTiddlers(filter);
 | 
					 | 
				
			||||||
	$tw.utils.each(tiddlers,function(title) {
 | 
					 | 
				
			||||||
		var renderTree = new $tw.WikiRenderTree(parser,{wiki: wiki, context: {tiddlerTitle: title}, document: $tw.document});
 | 
					 | 
				
			||||||
		renderTree.execute();
 | 
					 | 
				
			||||||
		var container = $tw.document.createElement("div");
 | 
					 | 
				
			||||||
		renderTree.renderInDom(container);
 | 
					 | 
				
			||||||
		var text = type === "text/html" ? container.innerHTML : container.textContent;
 | 
					 | 
				
			||||||
		fs.writeFileSync(path.resolve(pathname,encodeURIComponent(title) + extension),text,"utf8");
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	return null;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.Command = Command;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,212 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/rendertree/renderers/element.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: wikirenderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Element renderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Element widget. A degenerate widget that renders ordinary HTML elements
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
var ElementWidget = function(renderer) {
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	this.tag = this.renderer.parseTreeNode.tag;
 | 
					 | 
				
			||||||
	this.attributes = this.renderer.attributes;
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,this.renderer.parseTreeNode.children);
 | 
					 | 
				
			||||||
	this.events = this.renderer.parseTreeNode.events;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ElementWidget.prototype.refreshInDom = function(changedAttributes,changedTiddlers) {
 | 
					 | 
				
			||||||
	// Check if any of our attribute dependencies have changed
 | 
					 | 
				
			||||||
	if($tw.utils.count(changedAttributes) > 0) {
 | 
					 | 
				
			||||||
		// Update our attributes
 | 
					 | 
				
			||||||
		this.renderer.assignAttributes();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Refresh any child nodes
 | 
					 | 
				
			||||||
	$tw.utils.each(this.children,function(node) {
 | 
					 | 
				
			||||||
		if(node.refreshInDom) {
 | 
					 | 
				
			||||||
			node.refreshInDom(changedTiddlers);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Element renderer
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
var ElementRenderer = function(renderTree,parentRenderer,parseTreeNode) {
 | 
					 | 
				
			||||||
	// Store state information
 | 
					 | 
				
			||||||
	this.renderTree = renderTree;
 | 
					 | 
				
			||||||
	this.parentRenderer = parentRenderer;
 | 
					 | 
				
			||||||
	this.parseTreeNode = parseTreeNode;
 | 
					 | 
				
			||||||
	// Initialise widget classes
 | 
					 | 
				
			||||||
	if(!this.widgetClasses) {
 | 
					 | 
				
			||||||
		ElementRenderer.prototype.widgetClasses = $tw.modules.applyMethods("widget");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Select the namespace for the tag
 | 
					 | 
				
			||||||
	var tagNameSpaces = {
 | 
					 | 
				
			||||||
		svg: "http://www.w3.org/2000/svg",
 | 
					 | 
				
			||||||
		math: "http://www.w3.org/1998/Math/MathML"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	this.namespace = tagNameSpaces[this.parseTreeNode.tag];
 | 
					 | 
				
			||||||
	if(this.namespace) {
 | 
					 | 
				
			||||||
		this.context = this.context || {};
 | 
					 | 
				
			||||||
		this.context.namespace = this.namespace;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		this.namespace = this.renderTree.getContextVariable(this.parentRenderer,"namespace","http://www.w3.org/1999/xhtml");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Get the context tiddler title
 | 
					 | 
				
			||||||
	this.tiddlerTitle = this.renderTree.getContextVariable(this.parentRenderer,"tiddlerTitle");
 | 
					 | 
				
			||||||
	// Compute our dependencies
 | 
					 | 
				
			||||||
	this.dependencies = {};
 | 
					 | 
				
			||||||
	var self = this;
 | 
					 | 
				
			||||||
	$tw.utils.each(this.parseTreeNode.attributes,function(attribute,name) {
 | 
					 | 
				
			||||||
		if(attribute.type === "indirect") {
 | 
					 | 
				
			||||||
			var tr = $tw.utils.parseTextReference(attribute.textReference);
 | 
					 | 
				
			||||||
			self.dependencies[tr.title ? tr.title : self.tiddlerTitle] = true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	// Compute our attributes
 | 
					 | 
				
			||||||
	this.attributes = {};
 | 
					 | 
				
			||||||
	this.computeAttributes();
 | 
					 | 
				
			||||||
	// Create the parasite widget object if required
 | 
					 | 
				
			||||||
	if(this.parseTreeNode.tag.charAt(0) === "$") {
 | 
					 | 
				
			||||||
		// Choose the class
 | 
					 | 
				
			||||||
		var WidgetClass = this.widgetClasses[this.parseTreeNode.tag.substr(1)];
 | 
					 | 
				
			||||||
		// Instantiate the widget
 | 
					 | 
				
			||||||
		if(WidgetClass) {
 | 
					 | 
				
			||||||
			this.widget = new WidgetClass(this);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			WidgetClass = this.widgetClasses.error;
 | 
					 | 
				
			||||||
			if(WidgetClass) {
 | 
					 | 
				
			||||||
				this.widget = new WidgetClass(this,"Unknown widget '<" + this.parseTreeNode.tag + ">'");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// If we haven't got a widget, use the generic HTML element widget
 | 
					 | 
				
			||||||
	if(!this.widget) {
 | 
					 | 
				
			||||||
		this.widget = new ElementWidget(this);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ElementRenderer.prototype.computeAttributes = function() {
 | 
					 | 
				
			||||||
	var changedAttributes = {},
 | 
					 | 
				
			||||||
		self = this,
 | 
					 | 
				
			||||||
		value;
 | 
					 | 
				
			||||||
	$tw.utils.each(this.parseTreeNode.attributes,function(attribute,name) {
 | 
					 | 
				
			||||||
		if(attribute.type === "indirect") {
 | 
					 | 
				
			||||||
			value = self.renderTree.wiki.getTextReference(attribute.textReference,"",self.tiddlerTitle);
 | 
					 | 
				
			||||||
		} else if(attribute.type === "macro") {
 | 
					 | 
				
			||||||
			// Get the macro definition
 | 
					 | 
				
			||||||
			var macro = self.renderTree.findMacroDefinition(self.parentRenderer,attribute.value.name);
 | 
					 | 
				
			||||||
			if(!macro) {
 | 
					 | 
				
			||||||
				value = "";
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				// Substitute the macro parameters
 | 
					 | 
				
			||||||
				value = self.renderTree.substituteParameters(macro,attribute.value);
 | 
					 | 
				
			||||||
				// Parse the text and render it as text
 | 
					 | 
				
			||||||
				value = self.renderTree.wiki.renderText("text/plain","text/vnd.tiddlywiki",value,self.context);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else { // String attribute
 | 
					 | 
				
			||||||
			value = attribute.value;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// Check whether the attribute has changed
 | 
					 | 
				
			||||||
		if(self.attributes[name] !== value) {
 | 
					 | 
				
			||||||
			self.attributes[name] = value;
 | 
					 | 
				
			||||||
			changedAttributes[name] = true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	return changedAttributes;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ElementRenderer.prototype.hasAttribute = function(name) {
 | 
					 | 
				
			||||||
	return $tw.utils.hop(this.attributes,name);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ElementRenderer.prototype.getAttribute = function(name,defaultValue) {
 | 
					 | 
				
			||||||
	if($tw.utils.hop(this.attributes,name)) {
 | 
					 | 
				
			||||||
		return this.attributes[name];
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return defaultValue;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ElementRenderer.prototype.renderInDom = function() {
 | 
					 | 
				
			||||||
	// Check if our widget is providing an element
 | 
					 | 
				
			||||||
	if(this.widget.tag) {
 | 
					 | 
				
			||||||
		// Create the element
 | 
					 | 
				
			||||||
		this.domNode = this.renderTree.document.createElementNS(this.namespace,this.widget.tag);
 | 
					 | 
				
			||||||
		// Assign any specified event handlers
 | 
					 | 
				
			||||||
		$tw.utils.addEventListeners(this.domNode,this.widget.events);
 | 
					 | 
				
			||||||
		// Assign the attributes
 | 
					 | 
				
			||||||
		this.assignAttributes();
 | 
					 | 
				
			||||||
		// Render any child nodes
 | 
					 | 
				
			||||||
		var self = this;
 | 
					 | 
				
			||||||
		$tw.utils.each(this.widget.children,function(node) {
 | 
					 | 
				
			||||||
			if(node.renderInDom) {
 | 
					 | 
				
			||||||
				self.domNode.appendChild(node.renderInDom());
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
		// Call postRenderInDom if the widget provides it and we're in the browser
 | 
					 | 
				
			||||||
		if($tw.browser && this.widget.postRenderInDom) {
 | 
					 | 
				
			||||||
			this.widget.postRenderInDom();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// Return the dom node
 | 
					 | 
				
			||||||
		return this.domNode;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// If we're not generating an element, just render our first child
 | 
					 | 
				
			||||||
		return this.widget.children[0].renderInDom();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ElementRenderer.prototype.assignAttributes = function() {
 | 
					 | 
				
			||||||
	var self = this;
 | 
					 | 
				
			||||||
	$tw.utils.each(this.widget.attributes,function(v,a) {
 | 
					 | 
				
			||||||
		if(v !== undefined) {
 | 
					 | 
				
			||||||
			if($tw.utils.isArray(v)) { // Ahem, could there be arrays other than className?
 | 
					 | 
				
			||||||
				self.domNode.className = v.join(" "); 
 | 
					 | 
				
			||||||
			} else if (typeof v === "object") { // ...or objects other than style?
 | 
					 | 
				
			||||||
				for(var p in v) {
 | 
					 | 
				
			||||||
					self.domNode.style[$tw.utils.unHyphenateCss(p)] = v[p];
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				// Setting certain attributes can cause a DOM error (eg xmlns on the svg element)
 | 
					 | 
				
			||||||
				try {
 | 
					 | 
				
			||||||
					self.domNode.setAttributeNS(null,a,v);
 | 
					 | 
				
			||||||
				} catch(e) {
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ElementRenderer.prototype.refreshInDom = function(changedTiddlers) {
 | 
					 | 
				
			||||||
	// Update our attributes if required
 | 
					 | 
				
			||||||
	var changedAttributes = {};
 | 
					 | 
				
			||||||
	if($tw.utils.checkDependencies(this.dependencies,changedTiddlers)) {
 | 
					 | 
				
			||||||
		changedAttributes = this.computeAttributes();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Check if the widget has a refreshInDom method
 | 
					 | 
				
			||||||
	if(this.widget.refreshInDom) {
 | 
					 | 
				
			||||||
		// Let the widget refresh itself
 | 
					 | 
				
			||||||
		this.widget.refreshInDom(changedAttributes,changedTiddlers);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// If not, assign the attributes and refresh any child nodes
 | 
					 | 
				
			||||||
		this.assignAttributes();
 | 
					 | 
				
			||||||
		$tw.utils.each(this.widget.children,function(node) {
 | 
					 | 
				
			||||||
			if(node.refreshInDom) {
 | 
					 | 
				
			||||||
				node.refreshInDom(changedTiddlers);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.element = ElementRenderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,31 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/rendertree/renderers/entity.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: wikirenderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Entity renderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Entity renderer
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
var EntityRenderer = function(renderTree,parentRenderer,parseTreeNode) {
 | 
					 | 
				
			||||||
	// Store state information
 | 
					 | 
				
			||||||
	this.renderTree = renderTree;
 | 
					 | 
				
			||||||
	this.parentRenderer = parentRenderer;
 | 
					 | 
				
			||||||
	this.parseTreeNode = parseTreeNode;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EntityRenderer.prototype.renderInDom = function() {
 | 
					 | 
				
			||||||
	return this.renderTree.document.createTextNode($tw.utils.entityDecode(this.parseTreeNode.entity));
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.entity = EntityRenderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,65 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/rendertree/renderers/macrocall.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: wikirenderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Macro call renderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Macro call renderer
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
var MacroCallRenderer = function(renderTree,parentRenderer,parseTreeNode) {
 | 
					 | 
				
			||||||
	// Store state information
 | 
					 | 
				
			||||||
	this.renderTree = renderTree;
 | 
					 | 
				
			||||||
	this.parentRenderer = parentRenderer;
 | 
					 | 
				
			||||||
	this.parseTreeNode = parseTreeNode;
 | 
					 | 
				
			||||||
	// Find the macro definition
 | 
					 | 
				
			||||||
	var macro = this.renderTree.findMacroDefinition(this.parentRenderer,this.parseTreeNode.name);
 | 
					 | 
				
			||||||
	// Insert an error message if we couldn't find the macro
 | 
					 | 
				
			||||||
	var childTree;
 | 
					 | 
				
			||||||
	if(!macro) {
 | 
					 | 
				
			||||||
		childTree = [{type: "text", text: "<<Undefined macro: " + this.parseTreeNode.name + ">>"}];
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// Substitute the macro parameters
 | 
					 | 
				
			||||||
		var text = this.renderTree.substituteParameters(macro,this.parseTreeNode);
 | 
					 | 
				
			||||||
		// Parse the text
 | 
					 | 
				
			||||||
		childTree = this.renderTree.wiki.parseText("text/vnd.tiddlywiki",text,{parseAsInline: !this.parseTreeNode.isBlock}).tree;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Create the renderers for the child nodes
 | 
					 | 
				
			||||||
	this.children = this.renderTree.createRenderers(this,childTree);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MacroCallRenderer.prototype.renderInDom = function() {
 | 
					 | 
				
			||||||
	// Create the element
 | 
					 | 
				
			||||||
	this.domNode = this.renderTree.document.createElement(this.parseTreeNode.isBlock ? "div" : "span");
 | 
					 | 
				
			||||||
	this.domNode.setAttribute("data-macro-name",this.parseTreeNode.name);
 | 
					 | 
				
			||||||
	// Render any child nodes
 | 
					 | 
				
			||||||
	var self = this;
 | 
					 | 
				
			||||||
	$tw.utils.each(this.children,function(node,index) {
 | 
					 | 
				
			||||||
		if(node.renderInDom) {
 | 
					 | 
				
			||||||
			self.domNode.appendChild(node.renderInDom());
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	// Return the dom node
 | 
					 | 
				
			||||||
	return this.domNode;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MacroCallRenderer.prototype.refreshInDom = function(changedTiddlers) {
 | 
					 | 
				
			||||||
	// Refresh any child nodes
 | 
					 | 
				
			||||||
	$tw.utils.each(this.children,function(node) {
 | 
					 | 
				
			||||||
		if(node.refreshInDom) {
 | 
					 | 
				
			||||||
			node.refreshInDom(changedTiddlers);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.macrocall = MacroCallRenderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,30 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/rendertree/renderers/macrodef.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: wikirenderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Macro definition renderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Macro definition renderer
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
var MacroDefRenderer = function(renderTree,parentRenderer,parseTreeNode) {
 | 
					 | 
				
			||||||
	// Store state information
 | 
					 | 
				
			||||||
	this.renderTree = renderTree;
 | 
					 | 
				
			||||||
	this.parentRenderer = parentRenderer;
 | 
					 | 
				
			||||||
	this.parseTreeNode = parseTreeNode;
 | 
					 | 
				
			||||||
	// Save the macro definition into the context of the rendertree
 | 
					 | 
				
			||||||
	this.renderTree.context.macroDefinitions = this.renderTree.context.macroDefinitions || {};
 | 
					 | 
				
			||||||
	this.renderTree.context.macroDefinitions[this.parseTreeNode.name] = this.parseTreeNode;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.macrodef = MacroDefRenderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,33 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/rendertree/renderers/raw.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: wikirenderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Raw HTML renderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Raw HTML renderer
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
var RawRenderer = function(renderTree,parentRenderer,parseTreeNode) {
 | 
					 | 
				
			||||||
	// Store state information
 | 
					 | 
				
			||||||
	this.renderTree = renderTree;
 | 
					 | 
				
			||||||
	this.parentRenderer = parentRenderer;
 | 
					 | 
				
			||||||
	this.parseTreeNode = parseTreeNode;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RawRenderer.prototype.renderInDom = function() {
 | 
					 | 
				
			||||||
	var domNode = this.renderTree.document.createElement("div");
 | 
					 | 
				
			||||||
	domNode.innerHTML = this.parseTreeNode.html;
 | 
					 | 
				
			||||||
	return domNode;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.raw = RawRenderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,31 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/rendertree/renderers/text.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: wikirenderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Text renderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Text renderer
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
var TextRenderer = function(renderTree,parentRenderer,parseTreeNode) {
 | 
					 | 
				
			||||||
	// Store state information
 | 
					 | 
				
			||||||
	this.renderTree = renderTree;
 | 
					 | 
				
			||||||
	this.parentRenderer = parentRenderer;
 | 
					 | 
				
			||||||
	this.parseTreeNode = parseTreeNode;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TextRenderer.prototype.renderInDom = function() {
 | 
					 | 
				
			||||||
	return this.renderTree.document.createTextNode(this.parseTreeNode.text);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.text = TextRenderer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,198 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/rendertree/wikirendertree.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: global
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Wiki text render tree
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Create a render tree object for a parse tree
 | 
					 | 
				
			||||||
	parser: reference to the parse tree to be rendered
 | 
					 | 
				
			||||||
	options: see below
 | 
					 | 
				
			||||||
Options include:
 | 
					 | 
				
			||||||
	wiki: mandatory reference to wiki associated with this render tree
 | 
					 | 
				
			||||||
	context: optional hashmap of context variables (see below)
 | 
					 | 
				
			||||||
	parentRenderer: optional reference to a parent renderer node for the context chain
 | 
					 | 
				
			||||||
	document: optional document object to use instead of global document
 | 
					 | 
				
			||||||
Context variables include:
 | 
					 | 
				
			||||||
	tiddlerTitle: title of the tiddler providing the context
 | 
					 | 
				
			||||||
	templateTitle: title of the tiddler providing the current template
 | 
					 | 
				
			||||||
	macroDefinitions: hashmap of macro definitions
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
var WikiRenderTree = function(parser,options) {
 | 
					 | 
				
			||||||
	this.parser = parser;
 | 
					 | 
				
			||||||
	this.wiki = options.wiki;
 | 
					 | 
				
			||||||
	this.context = options.context || {};
 | 
					 | 
				
			||||||
	this.parentRenderer = options.parentRenderer;
 | 
					 | 
				
			||||||
	this.document = options.document;
 | 
					 | 
				
			||||||
	// Hashmap of the renderer classes
 | 
					 | 
				
			||||||
	if(!this.rendererClasses) {
 | 
					 | 
				
			||||||
		WikiRenderTree.prototype.rendererClasses = $tw.modules.applyMethods("wikirenderer");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Generate the full render tree for this parse tree
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
WikiRenderTree.prototype.execute = function() {
 | 
					 | 
				
			||||||
	this.rendererTree = this.createRenderers(this,this.parser.tree);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Create an array of renderers for an array of parse tree nodes
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
WikiRenderTree.prototype.createRenderers = function(parentRenderer,parseTreeNodes) {
 | 
					 | 
				
			||||||
	var rendererNodes = [];
 | 
					 | 
				
			||||||
	if(parseTreeNodes) {
 | 
					 | 
				
			||||||
		for(var t=0; t<parseTreeNodes.length; t++) {
 | 
					 | 
				
			||||||
			rendererNodes.push(this.createRenderer(parentRenderer,parseTreeNodes[t]));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return rendererNodes;
 | 
					 | 
				
			||||||
};	
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Create a renderer node for a parse tree node
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
WikiRenderTree.prototype.createRenderer = function(parentRenderer,parseTreeNode) {
 | 
					 | 
				
			||||||
	var RenderNodeClass = this.rendererClasses[parseTreeNode.type];
 | 
					 | 
				
			||||||
	return new RenderNodeClass(this,parentRenderer,parseTreeNode);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Render to the DOM
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
WikiRenderTree.prototype.renderInDom = function(container) {
 | 
					 | 
				
			||||||
	this.container = container;
 | 
					 | 
				
			||||||
	$tw.utils.each(this.rendererTree,function(node) {
 | 
					 | 
				
			||||||
		if(node.renderInDom) {
 | 
					 | 
				
			||||||
			container.appendChild(node.renderInDom());
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Update the DOM rendering in the light of a set of changes
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
WikiRenderTree.prototype.refreshInDom = function(changes) {
 | 
					 | 
				
			||||||
	$tw.utils.each(this.rendererTree,function(node) {
 | 
					 | 
				
			||||||
		if(node.refreshInDom) {
 | 
					 | 
				
			||||||
			node.refreshInDom(changes);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Find the value of a given context variable for a particular renderer node
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
WikiRenderTree.prototype.getContextVariable = function(renderer,name,defaultValue) {
 | 
					 | 
				
			||||||
	while(renderer) {
 | 
					 | 
				
			||||||
		if($tw.utils.hop(renderer.context,name)) {
 | 
					 | 
				
			||||||
			return renderer.context[name];
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		renderer = renderer.parentRenderer;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	return defaultValue;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Check for render context recursion from a particular renderer node by returning true if the members of a proposed new render context are already present in the render context chain
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
WikiRenderTree.prototype.checkContextRecursion = function(renderer,newContext) {
 | 
					 | 
				
			||||||
	while(renderer) {
 | 
					 | 
				
			||||||
		var context = renderer.context;
 | 
					 | 
				
			||||||
		if(context) {
 | 
					 | 
				
			||||||
			var match = true;
 | 
					 | 
				
			||||||
			for(var member in newContext) {
 | 
					 | 
				
			||||||
				if($tw.utils.hop(context,member)) {
 | 
					 | 
				
			||||||
					if(newContext[member] !== context[member]) {
 | 
					 | 
				
			||||||
						match = false;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					match = false;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if(match) {
 | 
					 | 
				
			||||||
				return true;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		renderer = renderer.parentRenderer;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WikiRenderTree.prototype.getContextScopeId = function(renderer) {
 | 
					 | 
				
			||||||
	var guidBits = [],
 | 
					 | 
				
			||||||
		scopeComponents = ["tiddlerTitle","templateTitle"],
 | 
					 | 
				
			||||||
		processContext = function(field,name) {
 | 
					 | 
				
			||||||
				if(scopeComponents.indexOf(name) !== -1) {
 | 
					 | 
				
			||||||
					guidBits.push(name + ":" + field + ";");
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
	while(renderer) {
 | 
					 | 
				
			||||||
		if(renderer.context) {
 | 
					 | 
				
			||||||
			$tw.utils.each(renderer.context,processContext);
 | 
					 | 
				
			||||||
			guidBits.push("-");
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		renderer = renderer.parentRenderer;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return guidBits.join("");
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Find a named macro definition
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
WikiRenderTree.prototype.findMacroDefinition = function(renderer,name) {
 | 
					 | 
				
			||||||
	while(renderer) {
 | 
					 | 
				
			||||||
		if(renderer.context && renderer.context.macroDefinitions && renderer.context.macroDefinitions[name]) {
 | 
					 | 
				
			||||||
			return renderer.context.macroDefinitions[name];
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		renderer = renderer.parentRenderer;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return undefined;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Expand the parameters of a macro
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
WikiRenderTree.prototype.substituteParameters = function(macroDefinition,macroCallParseTreeNode) {
 | 
					 | 
				
			||||||
	var text = macroDefinition.text,
 | 
					 | 
				
			||||||
		nextAnonParameter = 0; // Next candidate anonymous parameter in macro call
 | 
					 | 
				
			||||||
	// Step through each of the parameters in the macro definition
 | 
					 | 
				
			||||||
	for(var p=0; p<macroDefinition.params.length; p++) {
 | 
					 | 
				
			||||||
		// Check if we've got a macro call parameter with the same name
 | 
					 | 
				
			||||||
		var paramInfo = macroDefinition.params[p],
 | 
					 | 
				
			||||||
			paramValue = undefined;
 | 
					 | 
				
			||||||
		for(var m=0; m<macroCallParseTreeNode.params.length; m++) {
 | 
					 | 
				
			||||||
			if(macroCallParseTreeNode.params[m].name === paramInfo.name) {
 | 
					 | 
				
			||||||
				paramValue = macroCallParseTreeNode.params[m].value;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// If not, use the next available anonymous macro call parameter
 | 
					 | 
				
			||||||
		if(!paramValue && nextAnonParameter < macroCallParseTreeNode.params.length) {
 | 
					 | 
				
			||||||
			while(macroCallParseTreeNode.params[nextAnonParameter].name && nextAnonParameter < macroCallParseTreeNode.params.length-1) {
 | 
					 | 
				
			||||||
				nextAnonParameter++;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if(!macroCallParseTreeNode.params[nextAnonParameter].name) {
 | 
					 | 
				
			||||||
				paramValue = macroCallParseTreeNode.params[nextAnonParameter].value;
 | 
					 | 
				
			||||||
				nextAnonParameter++;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// If we've still not got a value, use the default, if any
 | 
					 | 
				
			||||||
		paramValue = paramValue || paramInfo["default"] || "";
 | 
					 | 
				
			||||||
		// Replace any instances of this parameter
 | 
					 | 
				
			||||||
		text = text.replace(new RegExp("\\$" + $tw.utils.escapeRegExp(paramInfo.name) + "\\$","mg"),paramValue);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return text;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.WikiRenderTree = WikiRenderTree;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,150 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/button.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Implements the button widget.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var ButtonWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ButtonWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get the parameters from the attributes
 | 
					 | 
				
			||||||
	this.message = this.renderer.getAttribute("message");
 | 
					 | 
				
			||||||
	this.param = this.renderer.getAttribute("param");
 | 
					 | 
				
			||||||
	this.set = this.renderer.getAttribute("set");
 | 
					 | 
				
			||||||
	this.setTo = this.renderer.getAttribute("setTo");
 | 
					 | 
				
			||||||
	this.popup = this.renderer.getAttribute("popup");
 | 
					 | 
				
			||||||
	this.hover = this.renderer.getAttribute("hover");
 | 
					 | 
				
			||||||
	this.qualifyTiddlerTitles = this.renderer.getAttribute("qualifyTiddlerTitles");
 | 
					 | 
				
			||||||
	this["class"] = this.renderer.getAttribute("class");
 | 
					 | 
				
			||||||
	this.selectedClass = this.renderer.getAttribute("selectedClass");
 | 
					 | 
				
			||||||
	// Compose the button
 | 
					 | 
				
			||||||
	var classes = ["tw-button"];
 | 
					 | 
				
			||||||
	if(this["class"]) {
 | 
					 | 
				
			||||||
		$tw.utils.pushTop(classes,this["class"]);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var events = [{name: "click", handlerObject: this, handlerMethod: "handleClickEvent"}];
 | 
					 | 
				
			||||||
	if(this.hover === "yes") {
 | 
					 | 
				
			||||||
		events.push({name: "mouseover", handlerObject: this, handlerMethod: "handleMouseOverOrOutEvent"});
 | 
					 | 
				
			||||||
		events.push({name: "mouseout", handlerObject: this, handlerMethod: "handleMouseOverOrOutEvent"});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(this.set && this.setTo && this.selectedClass) {
 | 
					 | 
				
			||||||
		if(this.isSelected()) {
 | 
					 | 
				
			||||||
			classes.push(this.selectedClass);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Set the return element
 | 
					 | 
				
			||||||
	this.tag = "button";
 | 
					 | 
				
			||||||
	this.attributes ={"class": classes.join(" ")};
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,this.renderer.parseTreeNode.children);
 | 
					 | 
				
			||||||
	this.events = events;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ButtonWidget.prototype.dispatchMessage = function(event) {
 | 
					 | 
				
			||||||
	$tw.utils.dispatchCustomEvent(event.target,this.message,{
 | 
					 | 
				
			||||||
		param: this.param,
 | 
					 | 
				
			||||||
		tiddlerTitle: this.renderer.tiddlerTitle
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ButtonWidget.prototype.triggerPopup = function(event) {
 | 
					 | 
				
			||||||
	var title = this.popup;
 | 
					 | 
				
			||||||
	if(this.qualifyTiddlerTitles) {
 | 
					 | 
				
			||||||
		title =  title + "-" + this.renderer.renderTree.getContextScopeId(this.renderer.parentRenderer);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	$tw.popup.triggerPopup({
 | 
					 | 
				
			||||||
		domNode: this.renderer.domNode,
 | 
					 | 
				
			||||||
		title: title,
 | 
					 | 
				
			||||||
		wiki: this.renderer.renderTree.wiki
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ButtonWidget.prototype.isSelected = function() {
 | 
					 | 
				
			||||||
	var title = this.set;
 | 
					 | 
				
			||||||
	if(this.qualifyTiddlerTitles) {
 | 
					 | 
				
			||||||
		title =  title + "-" + this.renderer.renderTree.getContextScopeId(this.renderer.parentRenderer);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var tiddler = this.renderer.renderTree.wiki.getTiddler(title);
 | 
					 | 
				
			||||||
	return tiddler ? tiddler.fields.text === this.setTo : false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ButtonWidget.prototype.setTiddler = function() {
 | 
					 | 
				
			||||||
	var title = this.set;
 | 
					 | 
				
			||||||
	if(this.qualifyTiddlerTitles) {
 | 
					 | 
				
			||||||
		title =  title + "-" + this.renderer.renderTree.getContextScopeId(this.renderer.parentRenderer);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var tiddler = this.renderer.renderTree.wiki.getTiddler(title);
 | 
					 | 
				
			||||||
	this.renderer.renderTree.wiki.addTiddler(new $tw.Tiddler(tiddler,{title: title, text: this.setTo}));
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ButtonWidget.prototype.handleClickEvent = function(event) {
 | 
					 | 
				
			||||||
	var handled = false;
 | 
					 | 
				
			||||||
	if(this.message) {
 | 
					 | 
				
			||||||
		this.dispatchMessage(event);
 | 
					 | 
				
			||||||
		handled = true;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(this.popup) {
 | 
					 | 
				
			||||||
		this.triggerPopup(event);
 | 
					 | 
				
			||||||
		handled = true;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(this.set) {
 | 
					 | 
				
			||||||
		this.setTiddler();
 | 
					 | 
				
			||||||
		handled = true;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	event.stopPropagation();
 | 
					 | 
				
			||||||
	event.preventDefault();
 | 
					 | 
				
			||||||
	return handled;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ButtonWidget.prototype.handleMouseOverOrOutEvent = function(event) {
 | 
					 | 
				
			||||||
	if(this.popup) {
 | 
					 | 
				
			||||||
		this.triggerPopup(event);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	event.preventDefault();
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ButtonWidget.prototype.refreshInDom = function(changedAttributes,changedTiddlers) {
 | 
					 | 
				
			||||||
	var setTitle = this.set,
 | 
					 | 
				
			||||||
		popupTitle = this.popup;
 | 
					 | 
				
			||||||
	if(this.qualifyTiddlerTitles) {
 | 
					 | 
				
			||||||
		var scopeId = this.renderer.renderTree.getContextScopeId(this.renderer.parentRenderer);
 | 
					 | 
				
			||||||
		if(setTitle) {
 | 
					 | 
				
			||||||
			setTitle =  setTitle + "-" + scopeId;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if(popupTitle) {
 | 
					 | 
				
			||||||
			popupTitle =  popupTitle + "-" + scopeId;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Check if any of our attributes have changed, or if a tiddler we're interested in has changed
 | 
					 | 
				
			||||||
 	if(changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.qualifyTiddlerTitles || changedAttributes["class"] || (setTitle && changedTiddlers[setTitle]) || (popupTitle && changedTiddlers[popupTitle])) {
 | 
					 | 
				
			||||||
		// 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);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// We don't need to refresh ourselves, so just refresh any child nodes
 | 
					 | 
				
			||||||
		$tw.utils.each(this.children,function(node) {
 | 
					 | 
				
			||||||
			if(node.refreshInDom) {
 | 
					 | 
				
			||||||
				node.refreshInDom(changedTiddlers);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.button = ButtonWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,111 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/checkbox.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Implements the checkbox widget.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
<$checkbox tag="done"/>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<$checkbox tiddler="HelloThere" tag="red"/>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<$checkbox tag="done">
 | 
					 | 
				
			||||||
<$view field="title" format="link"/>
 | 
					 | 
				
			||||||
</$checkbox>
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var CheckboxWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CheckboxWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get the parameters from the attributes
 | 
					 | 
				
			||||||
	this.tiddlerTitle = this.renderer.getAttribute("tiddler",this.renderer.tiddlerTitle);
 | 
					 | 
				
			||||||
	this.tagName = this.renderer.getAttribute("tag");
 | 
					 | 
				
			||||||
	this["class"] = this.renderer.getAttribute("class");
 | 
					 | 
				
			||||||
	// Compute classes
 | 
					 | 
				
			||||||
	var classes = ["tw-checkbox"];
 | 
					 | 
				
			||||||
	if(this["class"]) {
 | 
					 | 
				
			||||||
		$tw.utils.pushTop(classes,this["class"]);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Create the checkbox and span elements
 | 
					 | 
				
			||||||
	var nodeCheckbox = {
 | 
					 | 
				
			||||||
			type: "element",
 | 
					 | 
				
			||||||
			tag: "input",
 | 
					 | 
				
			||||||
			attributes: {
 | 
					 | 
				
			||||||
				type: {type: "string", value: "checkbox"}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		nodeSpan = {
 | 
					 | 
				
			||||||
			type: "element",
 | 
					 | 
				
			||||||
			tag: "span",
 | 
					 | 
				
			||||||
			children: this.renderer.parseTreeNode.children
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	// Set the state of the checkbox
 | 
					 | 
				
			||||||
	if(this.getValue()) {
 | 
					 | 
				
			||||||
		$tw.utils.addAttributeToParseTreeNode(nodeCheckbox,"checked","true");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Set the return element
 | 
					 | 
				
			||||||
	this.tag = "label";
 | 
					 | 
				
			||||||
	this.attributes ={"class": classes.join(" ")};
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,[nodeCheckbox,nodeSpan]);
 | 
					 | 
				
			||||||
	this.events = [{name: "change", handlerObject: this, handlerMethod: "handleChangeEvent"}];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CheckboxWidget.prototype.getValue = function() {
 | 
					 | 
				
			||||||
	var tiddler = this.renderer.renderTree.wiki.getTiddler(this.tiddlerTitle);
 | 
					 | 
				
			||||||
	return tiddler ? tiddler.hasTag(this.tagName) : false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CheckboxWidget.prototype.handleChangeEvent  = function(event) {
 | 
					 | 
				
			||||||
	var checked = this.children[0].domNode.checked,
 | 
					 | 
				
			||||||
		tiddler = this.renderer.renderTree.wiki.getTiddler(this.tiddlerTitle);
 | 
					 | 
				
			||||||
	if(tiddler && tiddler.hasTag(this.tagName) !== checked) {
 | 
					 | 
				
			||||||
		var newTags = tiddler.fields.tags.slice(0),
 | 
					 | 
				
			||||||
			pos = newTags.indexOf(this.tagName);
 | 
					 | 
				
			||||||
		if(pos !== -1) {
 | 
					 | 
				
			||||||
			newTags.splice(pos,1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if(checked) {
 | 
					 | 
				
			||||||
			newTags.push(this.tagName);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		this.renderer.renderTree.wiki.addTiddler(new $tw.Tiddler(tiddler,{tags: newTags}));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CheckboxWidget.prototype.refreshInDom = function(changedAttributes,changedTiddlers) {
 | 
					 | 
				
			||||||
	// Check if any of our attributes have changed, or if a tiddler we're interested in has changed
 | 
					 | 
				
			||||||
	if(changedAttributes.tiddler || changedAttributes.tag || changedAttributes["class"]) {
 | 
					 | 
				
			||||||
		// 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);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// Update the checkbox if necessary
 | 
					 | 
				
			||||||
		if(changedTiddlers[this.tiddlerTitle]) {
 | 
					 | 
				
			||||||
			this.children[0].domNode.checked = this.getValue();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// Refresh children
 | 
					 | 
				
			||||||
		$tw.utils.each(this.children,function(node) {
 | 
					 | 
				
			||||||
			if(node.refreshInDom) {
 | 
					 | 
				
			||||||
				node.refreshInDom(changedTiddlers);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.checkbox = CheckboxWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,59 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/count.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Implements the count widget that displays the number of tiddlers that match a filter
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var CountWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Execute the filter to get the initial count
 | 
					 | 
				
			||||||
	this.executeFilter();
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CountWidget.prototype.executeFilter = function() {
 | 
					 | 
				
			||||||
	// Get attributes
 | 
					 | 
				
			||||||
	this.filter = this.renderer.getAttribute("filter");
 | 
					 | 
				
			||||||
	// Execute the filter
 | 
					 | 
				
			||||||
	if(this.filter) {
 | 
					 | 
				
			||||||
		this.currentCount = this.renderer.renderTree.wiki.filterTiddlers(this.filter,this.renderer.tiddlerTitle).length;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		this.currentCount = undefined;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CountWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Set the element
 | 
					 | 
				
			||||||
	this.tag = "span";
 | 
					 | 
				
			||||||
	this.attributes = {};
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,[
 | 
					 | 
				
			||||||
		{type: "text", text: this.currentCount !== undefined ? this.currentCount.toString() : ""}
 | 
					 | 
				
			||||||
	]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CountWidget.prototype.refreshInDom = function(changedAttributes,changedTiddlers) {
 | 
					 | 
				
			||||||
	// Re-execute the filter to get the count
 | 
					 | 
				
			||||||
	var oldCount = this.currentCount;
 | 
					 | 
				
			||||||
	this.executeFilter();
 | 
					 | 
				
			||||||
	if(this.currentCount !== oldCount) {
 | 
					 | 
				
			||||||
		// 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);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.count = CountWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,53 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/datauri.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The datauri widget displays the contents of a tiddler as a data URI.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var DataUriWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
DataUriWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get parameters from our attributes
 | 
					 | 
				
			||||||
	this.tiddlerTitle = this.renderer.getAttribute("tiddler",this.renderer.tiddlerTitle);
 | 
					 | 
				
			||||||
	// Compose the data URI
 | 
					 | 
				
			||||||
	var tiddler = this.renderer.renderTree.wiki.getTiddler(this.tiddlerTitle),
 | 
					 | 
				
			||||||
		uri = "";
 | 
					 | 
				
			||||||
	if(tiddler) {
 | 
					 | 
				
			||||||
		var type = tiddler.fields.type || "text/vnd.tiddlywiki",
 | 
					 | 
				
			||||||
			typeInfo = $tw.config.contentTypeInfo[type],
 | 
					 | 
				
			||||||
			isBase64 = typeInfo && typeInfo.encoding === "base64",
 | 
					 | 
				
			||||||
			parts = ["data:"];
 | 
					 | 
				
			||||||
		parts.push(type);
 | 
					 | 
				
			||||||
		parts.push(isBase64 ? ";base64" : "");
 | 
					 | 
				
			||||||
		parts.push(",");
 | 
					 | 
				
			||||||
		parts.push(isBase64 ? tiddler.fields.text : encodeURIComponent(tiddler.fields.text));
 | 
					 | 
				
			||||||
		uri = parts.join("");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Set the element
 | 
					 | 
				
			||||||
	this.tag = "pre";
 | 
					 | 
				
			||||||
	this.attributes = {
 | 
					 | 
				
			||||||
		"class": "tw-data-uri"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	// Create the renderers for the wrapper and the children
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,[{
 | 
					 | 
				
			||||||
		type: "text",
 | 
					 | 
				
			||||||
		text: uri
 | 
					 | 
				
			||||||
	}]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.datauri = DataUriWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,87 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/edit/edit.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The edit widget uses editor plugins to edit tiddlers of different types.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var EditWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Initialise the editors if they've not been done already
 | 
					 | 
				
			||||||
	if(!this.editors) {
 | 
					 | 
				
			||||||
		EditWidget.prototype.editors = {};
 | 
					 | 
				
			||||||
		$tw.modules.applyMethods("editor",this.editors);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EditWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get parameters from our attributes
 | 
					 | 
				
			||||||
	this.tiddlerTitle = this.renderer.getAttribute("tiddler",this.renderer.tiddlerTitle);
 | 
					 | 
				
			||||||
	this.fieldName = this.renderer.getAttribute("field");
 | 
					 | 
				
			||||||
	this.indexName = this.renderer.getAttribute("index");
 | 
					 | 
				
			||||||
	if(!this.fieldName && !this.indexName) {
 | 
					 | 
				
			||||||
		this.fieldName = "text";
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Choose the editor to use
 | 
					 | 
				
			||||||
	// TODO: Tiddler field modules should be able to specify a field type from which the editor is derived
 | 
					 | 
				
			||||||
	this.editorName = this.chooseEditor();
 | 
					 | 
				
			||||||
	var Editor = this.editors[this.editorName];
 | 
					 | 
				
			||||||
	// Instantiate the editor
 | 
					 | 
				
			||||||
	this.editor = new Editor(this,this.tiddlerTitle,this.fieldName,this.indexName);
 | 
					 | 
				
			||||||
	// Ask the editor to create the widget element
 | 
					 | 
				
			||||||
	this.editor.render();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Return the name of the editor that should handle this tiddler field
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
EditWidget.prototype.chooseEditor = function() {
 | 
					 | 
				
			||||||
	var tiddler = this.renderer.renderTree.wiki.getTiddler(this.tiddlerTitle);
 | 
					 | 
				
			||||||
	if(this.fieldName === "text" && tiddler && tiddler.fields.type && this.editors[tiddler.fields.type]) {
 | 
					 | 
				
			||||||
		return tiddler.fields.type;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return "text/vnd.tiddlywiki";
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EditWidget.prototype.postRenderInDom = function() {
 | 
					 | 
				
			||||||
	if(this.editor && this.editor.postRenderInDom) {
 | 
					 | 
				
			||||||
		this.editor.postRenderInDom();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EditWidget.prototype.refreshInDom = function(changedAttributes,changedTiddlers) {
 | 
					 | 
				
			||||||
	// We'll completely regenerate ourselves if any of our attributes have changed
 | 
					 | 
				
			||||||
	if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.format || this.chooseEditor() !== this.editorName) {
 | 
					 | 
				
			||||||
		// 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);
 | 
					 | 
				
			||||||
	} else if(this.tiddlerTitle && changedTiddlers[this.tiddlerTitle]) {
 | 
					 | 
				
			||||||
		// Refresh the editor if our tiddler has changed
 | 
					 | 
				
			||||||
		if(this.editor && this.editor.refreshInDom) {
 | 
					 | 
				
			||||||
			this.editor.refreshInDom(changedTiddlers);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// Otherwise, just refresh any child nodes
 | 
					 | 
				
			||||||
		$tw.utils.each(this.children,function(node) {
 | 
					 | 
				
			||||||
			if(node.refreshInDom) {
 | 
					 | 
				
			||||||
				node.refreshInDom(changedTiddlers);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.edit = EditWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,318 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/edit/editors/bitmapeditor.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: editor
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A bitmap editor
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Default images sizes
 | 
					 | 
				
			||||||
var DEFAULT_IMAGE_WIDTH = 300,
 | 
					 | 
				
			||||||
	DEFAULT_IMAGE_HEIGHT = 185;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// The elements of the editor UI
 | 
					 | 
				
			||||||
var DOM_CANVAS = 0,
 | 
					 | 
				
			||||||
	DOM_WIDTH = 1,
 | 
					 | 
				
			||||||
	DOM_HEIGHT = 2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var BitmapEditor = function(editWidget,tiddlerTitle,fieldName,indexName) {
 | 
					 | 
				
			||||||
	this.editWidget = editWidget;
 | 
					 | 
				
			||||||
	this.tiddlerTitle = tiddlerTitle;
 | 
					 | 
				
			||||||
	this.fieldName = fieldName;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BitmapEditor.prototype.render = function() {
 | 
					 | 
				
			||||||
	// Set the element details
 | 
					 | 
				
			||||||
	this.editWidget.tag = "div";
 | 
					 | 
				
			||||||
	this.editWidget.attributes = {
 | 
					 | 
				
			||||||
		"class": "tw-edit-bitmapeditor-wrapper"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	var children = [{
 | 
					 | 
				
			||||||
		type: "element",
 | 
					 | 
				
			||||||
		tag: "canvas",
 | 
					 | 
				
			||||||
		attributes: {
 | 
					 | 
				
			||||||
			"class": {type: "string", value: "tw-edit-bitmapeditor"}
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		events: [{
 | 
					 | 
				
			||||||
			name: "touchstart",
 | 
					 | 
				
			||||||
			handlerObject: this,
 | 
					 | 
				
			||||||
			handlerMethod: "handleTouchStartEvent"
 | 
					 | 
				
			||||||
		},{
 | 
					 | 
				
			||||||
			name: "touchmove",
 | 
					 | 
				
			||||||
			handlerObject: this,
 | 
					 | 
				
			||||||
			handlerMethod: "handleTouchMoveEvent"
 | 
					 | 
				
			||||||
		},{
 | 
					 | 
				
			||||||
			name: "touchend",
 | 
					 | 
				
			||||||
			handlerObject: this,
 | 
					 | 
				
			||||||
			handlerMethod: "handleTouchEndEvent"
 | 
					 | 
				
			||||||
		},{
 | 
					 | 
				
			||||||
			name: "mousedown",
 | 
					 | 
				
			||||||
			handlerObject: this,
 | 
					 | 
				
			||||||
			handlerMethod: "handleMouseDownEvent"
 | 
					 | 
				
			||||||
		},{
 | 
					 | 
				
			||||||
			name: "mousemove",
 | 
					 | 
				
			||||||
			handlerObject: this,
 | 
					 | 
				
			||||||
			handlerMethod: "handleMouseMoveEvent"
 | 
					 | 
				
			||||||
		},{
 | 
					 | 
				
			||||||
			name: "mouseup",
 | 
					 | 
				
			||||||
			handlerObject: this,
 | 
					 | 
				
			||||||
			handlerMethod: "handleMouseUpEvent"
 | 
					 | 
				
			||||||
		}]
 | 
					 | 
				
			||||||
	},{
 | 
					 | 
				
			||||||
		type: "element",
 | 
					 | 
				
			||||||
		tag: "input",
 | 
					 | 
				
			||||||
		attributes: {
 | 
					 | 
				
			||||||
			"class": {type: "string", value: "tw-edit-bitmapeditor-width"},
 | 
					 | 
				
			||||||
			"type": {type: "string", value: "number"},
 | 
					 | 
				
			||||||
			"value": {type: "string", value: ""}
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		events: [{
 | 
					 | 
				
			||||||
			name: "change",
 | 
					 | 
				
			||||||
			handlerObject: this,
 | 
					 | 
				
			||||||
			handlerMethod: "handleWidthChangeEvent"
 | 
					 | 
				
			||||||
		}]
 | 
					 | 
				
			||||||
	},{
 | 
					 | 
				
			||||||
		type: "element",
 | 
					 | 
				
			||||||
		tag: "input",
 | 
					 | 
				
			||||||
		attributes: {
 | 
					 | 
				
			||||||
			"class": {type: "string", value: "tw-edit-bitmapeditor-height"},
 | 
					 | 
				
			||||||
			"type": {type: "string", value: "number"},
 | 
					 | 
				
			||||||
			"value": {type: "string", value: ""}
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		events: [{
 | 
					 | 
				
			||||||
			name: "change",
 | 
					 | 
				
			||||||
			handlerObject: this,
 | 
					 | 
				
			||||||
			handlerMethod: "handleHeightChangeEvent"
 | 
					 | 
				
			||||||
		}]
 | 
					 | 
				
			||||||
	}];
 | 
					 | 
				
			||||||
	this.editWidget.children = this.editWidget.renderer.renderTree.createRenderers(this.editWidget.renderer,children);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BitmapEditor.prototype.postRenderInDom = function() {
 | 
					 | 
				
			||||||
	var tiddler = this.editWidget.renderer.renderTree.wiki.getTiddler(this.tiddlerTitle),
 | 
					 | 
				
			||||||
		canvas = this.getDomNode(DOM_CANVAS),
 | 
					 | 
				
			||||||
		currImage = new Image();
 | 
					 | 
				
			||||||
	// Set up event handlers for loading the image
 | 
					 | 
				
			||||||
	var self = this;
 | 
					 | 
				
			||||||
	currImage.onload = function() {
 | 
					 | 
				
			||||||
		// Copy the image to the on-screen canvas
 | 
					 | 
				
			||||||
		self.initCanvas(canvas,currImage.width,currImage.height,currImage);
 | 
					 | 
				
			||||||
		// And also copy the current bitmap to the off-screen canvas
 | 
					 | 
				
			||||||
		self.currCanvas = self.editWidget.renderer.renderTree.document.createElement("canvas");
 | 
					 | 
				
			||||||
		self.initCanvas(self.currCanvas,currImage.width,currImage.height,currImage);
 | 
					 | 
				
			||||||
		// Set the width and height input boxes
 | 
					 | 
				
			||||||
		self.updateSize();
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	currImage.onerror = function() {
 | 
					 | 
				
			||||||
		// Set the on-screen canvas size and clear it
 | 
					 | 
				
			||||||
		self.initCanvas(canvas,DEFAULT_IMAGE_WIDTH,DEFAULT_IMAGE_HEIGHT);
 | 
					 | 
				
			||||||
		// Set the off-screen canvas size and clear it
 | 
					 | 
				
			||||||
		self.currCanvas = self.editWidget.renderer.renderTree.document.createElement("canvas");
 | 
					 | 
				
			||||||
		self.initCanvas(self.currCanvas,DEFAULT_IMAGE_WIDTH,DEFAULT_IMAGE_HEIGHT);
 | 
					 | 
				
			||||||
		// Set the width and height input boxes
 | 
					 | 
				
			||||||
		self.updateSize();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Get the current bitmap into an image object
 | 
					 | 
				
			||||||
	currImage.src = "data:" + tiddler.fields.type + ";base64," + tiddler.fields.text;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BitmapEditor.prototype.initCanvas = function(canvas,width,height,image) {
 | 
					 | 
				
			||||||
	canvas.width = width;
 | 
					 | 
				
			||||||
	canvas.height = height;
 | 
					 | 
				
			||||||
	var ctx = canvas.getContext("2d");
 | 
					 | 
				
			||||||
	if(image) {
 | 
					 | 
				
			||||||
		ctx.drawImage(image,0,0);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		ctx.fillStyle = "#fff";
 | 
					 | 
				
			||||||
		ctx.fillRect(0,0,canvas.width,canvas.height);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BitmapEditor.prototype.getDomNode = function(index) {
 | 
					 | 
				
			||||||
	return this.editWidget.renderer.domNode.childNodes[index];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
** Update the input boxes with the actual size of the canvas
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
BitmapEditor.prototype.updateSize = function() {
 | 
					 | 
				
			||||||
	this.getDomNode(DOM_WIDTH).value = this.currCanvas.width;
 | 
					 | 
				
			||||||
	this.getDomNode(DOM_HEIGHT).value = this.currCanvas.height;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
** Change the size of the canvas, preserving the current image
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
BitmapEditor.prototype.changeCanvasSize = function(newWidth,newHeight) {
 | 
					 | 
				
			||||||
	// Create and size a new canvas
 | 
					 | 
				
			||||||
	var newCanvas = this.editWidget.renderer.renderTree.document.createElement("canvas");
 | 
					 | 
				
			||||||
	this.initCanvas(newCanvas,newWidth,newHeight);
 | 
					 | 
				
			||||||
	// Copy the old image
 | 
					 | 
				
			||||||
	var ctx = newCanvas.getContext("2d");
 | 
					 | 
				
			||||||
	ctx.drawImage(this.currCanvas,0,0);
 | 
					 | 
				
			||||||
	// Set the new canvas as the current one
 | 
					 | 
				
			||||||
	this.currCanvas = newCanvas;
 | 
					 | 
				
			||||||
	// Set the size of the onscreen canvas
 | 
					 | 
				
			||||||
	var canvas = this.getDomNode(DOM_CANVAS);
 | 
					 | 
				
			||||||
	canvas.width = newWidth;
 | 
					 | 
				
			||||||
	canvas.height = newHeight;
 | 
					 | 
				
			||||||
	// Paint the onscreen canvas with the offscreen canvas
 | 
					 | 
				
			||||||
	ctx = canvas.getContext("2d");
 | 
					 | 
				
			||||||
	ctx.drawImage(this.currCanvas,0,0);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BitmapEditor.prototype.handleWidthChangeEvent = function(event) {
 | 
					 | 
				
			||||||
	// Get the new width
 | 
					 | 
				
			||||||
	var newWidth = parseInt(this.getDomNode(DOM_WIDTH).value,10);
 | 
					 | 
				
			||||||
	// Update if necessary
 | 
					 | 
				
			||||||
	if(newWidth > 0 && newWidth !== this.currCanvas.width) {
 | 
					 | 
				
			||||||
		this.changeCanvasSize(newWidth,this.currCanvas.height);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Update the input controls
 | 
					 | 
				
			||||||
	this.updateSize();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BitmapEditor.prototype.handleHeightChangeEvent = function(event) {
 | 
					 | 
				
			||||||
	// Get the new width
 | 
					 | 
				
			||||||
	var newHeight = parseInt(this.getDomNode(DOM_HEIGHT).value,10);
 | 
					 | 
				
			||||||
	// Update if necessary
 | 
					 | 
				
			||||||
	if(newHeight > 0 && newHeight !== this.currCanvas.height) {
 | 
					 | 
				
			||||||
		this.changeCanvasSize(this.currCanvas.width,newHeight);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Update the input controls
 | 
					 | 
				
			||||||
	this.updateSize();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BitmapEditor.prototype.handleTouchStartEvent = function(event) {
 | 
					 | 
				
			||||||
	this.brushDown = true;
 | 
					 | 
				
			||||||
	this.strokeStart(event.touches[0].clientX,event.touches[0].clientY);
 | 
					 | 
				
			||||||
	event.preventDefault();
 | 
					 | 
				
			||||||
	event.stopPropagation();
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BitmapEditor.prototype.handleTouchMoveEvent = function(event) {
 | 
					 | 
				
			||||||
	if(this.brushDown) {
 | 
					 | 
				
			||||||
		this.strokeMove(event.touches[0].clientX,event.touches[0].clientY);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	event.preventDefault();
 | 
					 | 
				
			||||||
	event.stopPropagation();
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BitmapEditor.prototype.handleTouchEndEvent = function(event) {
 | 
					 | 
				
			||||||
	if(this.brushDown) {
 | 
					 | 
				
			||||||
		this.brushDown = false;
 | 
					 | 
				
			||||||
		this.strokeEnd();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	event.preventDefault();
 | 
					 | 
				
			||||||
	event.stopPropagation();
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BitmapEditor.prototype.handleMouseDownEvent = function(event) {
 | 
					 | 
				
			||||||
	this.strokeStart(event.clientX,event.clientY);
 | 
					 | 
				
			||||||
	this.brushDown = true;
 | 
					 | 
				
			||||||
	event.preventDefault();
 | 
					 | 
				
			||||||
	event.stopPropagation();
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BitmapEditor.prototype.handleMouseMoveEvent = function(event) {
 | 
					 | 
				
			||||||
	if(this.brushDown) {
 | 
					 | 
				
			||||||
		this.strokeMove(event.clientX,event.clientY);
 | 
					 | 
				
			||||||
		event.preventDefault();
 | 
					 | 
				
			||||||
		event.stopPropagation();
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BitmapEditor.prototype.handleMouseUpEvent = function(event) {
 | 
					 | 
				
			||||||
	if(this.brushDown) {
 | 
					 | 
				
			||||||
		this.brushDown = false;
 | 
					 | 
				
			||||||
		this.strokeEnd();
 | 
					 | 
				
			||||||
		event.preventDefault();
 | 
					 | 
				
			||||||
		event.stopPropagation();
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BitmapEditor.prototype.adjustCoordinates = function(x,y) {
 | 
					 | 
				
			||||||
	var canvas = this.getDomNode(DOM_CANVAS),
 | 
					 | 
				
			||||||
		canvasRect = canvas.getBoundingClientRect(),
 | 
					 | 
				
			||||||
		scale = canvas.width/canvasRect.width;
 | 
					 | 
				
			||||||
	return {x: (x - canvasRect.left) * scale, y: (y - canvasRect.top) * scale};
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BitmapEditor.prototype.strokeStart = function(x,y) {
 | 
					 | 
				
			||||||
	// Start off a new stroke
 | 
					 | 
				
			||||||
	this.stroke = [this.adjustCoordinates(x,y)];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BitmapEditor.prototype.strokeMove = function(x,y) {
 | 
					 | 
				
			||||||
	var canvas = this.getDomNode(DOM_CANVAS),
 | 
					 | 
				
			||||||
		ctx = canvas.getContext("2d"),
 | 
					 | 
				
			||||||
		t;
 | 
					 | 
				
			||||||
	// Add the new position to the end of the stroke
 | 
					 | 
				
			||||||
	this.stroke.push(this.adjustCoordinates(x,y));
 | 
					 | 
				
			||||||
	// Redraw the previous image
 | 
					 | 
				
			||||||
	ctx.drawImage(this.currCanvas,0,0);
 | 
					 | 
				
			||||||
	// Render the stroke
 | 
					 | 
				
			||||||
	ctx.strokeStyle = "#ff0";
 | 
					 | 
				
			||||||
	ctx.lineWidth = 3;
 | 
					 | 
				
			||||||
	ctx.lineCap = "round";
 | 
					 | 
				
			||||||
	ctx.lineJoin = "round";
 | 
					 | 
				
			||||||
	ctx.beginPath();
 | 
					 | 
				
			||||||
	ctx.moveTo(this.stroke[0].x,this.stroke[0].y);
 | 
					 | 
				
			||||||
	for(t=1; t<this.stroke.length-1; t++) {
 | 
					 | 
				
			||||||
		var s1 = this.stroke[t],
 | 
					 | 
				
			||||||
			s2 = this.stroke[t-1],
 | 
					 | 
				
			||||||
			tx = (s1.x + s2.x)/2,
 | 
					 | 
				
			||||||
			ty = (s1.y + s2.y)/2;
 | 
					 | 
				
			||||||
		ctx.quadraticCurveTo(s2.x,s2.y,tx,ty);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ctx.stroke();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BitmapEditor.prototype.strokeEnd = function() {
 | 
					 | 
				
			||||||
	// Copy the bitmap to the off-screen canvas
 | 
					 | 
				
			||||||
	var canvas = this.getDomNode(DOM_CANVAS),
 | 
					 | 
				
			||||||
		ctx = this.currCanvas.getContext("2d");
 | 
					 | 
				
			||||||
	ctx.drawImage(canvas,0,0);
 | 
					 | 
				
			||||||
	// Save the image into the tiddler
 | 
					 | 
				
			||||||
	this.saveChanges();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BitmapEditor.prototype.saveChanges = function() {
 | 
					 | 
				
			||||||
	var tiddler = this.editWidget.renderer.renderTree.wiki.getTiddler(this.tiddlerTitle);
 | 
					 | 
				
			||||||
	if(tiddler) {
 | 
					 | 
				
			||||||
		// data URIs look like "data:<type>;base64,<text>"
 | 
					 | 
				
			||||||
		var dataURL = this.getDomNode(DOM_CANVAS).toDataURL(tiddler.fields.type,1.0),
 | 
					 | 
				
			||||||
			posColon = dataURL.indexOf(":"),
 | 
					 | 
				
			||||||
			posSemiColon = dataURL.indexOf(";"),
 | 
					 | 
				
			||||||
			posComma = dataURL.indexOf(","),
 | 
					 | 
				
			||||||
			type = dataURL.substring(posColon+1,posSemiColon),
 | 
					 | 
				
			||||||
			text = dataURL.substring(posComma+1);
 | 
					 | 
				
			||||||
		var update = {type: type, text: text};
 | 
					 | 
				
			||||||
		this.editWidget.renderer.renderTree.wiki.addTiddler(new $tw.Tiddler(tiddler,update));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Note that the bitmap editor intentionally doesn't have a refreshInDom method to avoid the situation where a bitmap being editted is modified externally
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports["image/jpg"] = BitmapEditor;
 | 
					 | 
				
			||||||
exports["image/jpeg"] = BitmapEditor;
 | 
					 | 
				
			||||||
exports["image/png"] = BitmapEditor;
 | 
					 | 
				
			||||||
exports["image/gif"] = BitmapEditor;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,219 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/edit/editors/texteditor.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: editor
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A plain text editor
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var MIN_TEXT_AREA_HEIGHT = 100;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var TextEditor = function(editWidget,tiddlerTitle,fieldName,indexName) {
 | 
					 | 
				
			||||||
	this.editWidget = editWidget;
 | 
					 | 
				
			||||||
	this.tiddlerTitle = tiddlerTitle;
 | 
					 | 
				
			||||||
	this.fieldName = fieldName;
 | 
					 | 
				
			||||||
	this.indexName = indexName;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Get the tiddler being edited and current value
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
TextEditor.prototype.getEditInfo = function() {
 | 
					 | 
				
			||||||
	var tiddler = this.editWidget.renderer.renderTree.wiki.getTiddler(this.tiddlerTitle),
 | 
					 | 
				
			||||||
		value;
 | 
					 | 
				
			||||||
	if(this.fieldName) {
 | 
					 | 
				
			||||||
		// Get the current tiddler and the field name
 | 
					 | 
				
			||||||
		if(tiddler) {
 | 
					 | 
				
			||||||
			// If we've got a tiddler, the value to display is the field string value
 | 
					 | 
				
			||||||
			value = tiddler.getFieldString(this.fieldName);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			// Otherwise, we need to construct a default value for the editor
 | 
					 | 
				
			||||||
			switch(this.fieldName) {
 | 
					 | 
				
			||||||
				case "text":
 | 
					 | 
				
			||||||
					value = "Type the text for the tiddler '" + this.tiddlerTitle + "'";
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				case "title":
 | 
					 | 
				
			||||||
					value = this.tiddlerTitle;
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				default:
 | 
					 | 
				
			||||||
					value = "";
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			value = this.editWidget.renderer.getAttribute("default",value);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		value = this.editWidget.renderer.renderTree.wiki.extractTiddlerDataItem(this.tiddlerTitle,this.indexName,this.editWidget.renderer.getAttribute("default"));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return {tiddler: tiddler, value: value};
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TextEditor.prototype.render = function() {
 | 
					 | 
				
			||||||
	// Get the initial value of the editor
 | 
					 | 
				
			||||||
	var editInfo = this.getEditInfo();
 | 
					 | 
				
			||||||
	// Create the editor nodes
 | 
					 | 
				
			||||||
	var node = {
 | 
					 | 
				
			||||||
		type: "element",
 | 
					 | 
				
			||||||
		attributes: {}
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	// Get the edit type associated with this field
 | 
					 | 
				
			||||||
	var type = "input";
 | 
					 | 
				
			||||||
	if(this.fieldName === "text") {
 | 
					 | 
				
			||||||
		type = "textarea";
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		var fieldModule = $tw.Tiddler.fieldModules[this.fieldName];
 | 
					 | 
				
			||||||
		if(fieldModule && fieldModule.editType) {
 | 
					 | 
				
			||||||
			type = fieldModule.editType;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var type = this.editWidget.renderer.getAttribute("type",type);
 | 
					 | 
				
			||||||
	switch(type) {
 | 
					 | 
				
			||||||
		case "textarea":
 | 
					 | 
				
			||||||
			node.tag = "textarea";
 | 
					 | 
				
			||||||
			node.children = [{
 | 
					 | 
				
			||||||
				type: "text",
 | 
					 | 
				
			||||||
				text: editInfo.value
 | 
					 | 
				
			||||||
			}];
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case "color":
 | 
					 | 
				
			||||||
			node.tag = "input";
 | 
					 | 
				
			||||||
			node.attributes.type = {type: "string", value: "color"};
 | 
					 | 
				
			||||||
			node.attributes.value = {type: "string", value: editInfo.value};
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case "search":
 | 
					 | 
				
			||||||
			node.tag = "input";
 | 
					 | 
				
			||||||
			node.attributes.type = {type: "string", value: "search"};
 | 
					 | 
				
			||||||
			node.attributes.value = {type: "string", value: editInfo.value};
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		default: // "input"
 | 
					 | 
				
			||||||
			node.tag = "input";
 | 
					 | 
				
			||||||
			node.attributes.type = {type: "string", value: "text"};
 | 
					 | 
				
			||||||
			node.attributes.value = {type: "string", value: editInfo.value};
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	node.events = [
 | 
					 | 
				
			||||||
		{name: "focus", handlerObject: this, handlerMethod: "handleFocusEvent"},
 | 
					 | 
				
			||||||
		{name: "blur", handlerObject: this, handlerMethod: "handleBlurEvent"},
 | 
					 | 
				
			||||||
		{name: "input", handlerObject: this, handlerMethod: "handleInputEvent"}
 | 
					 | 
				
			||||||
	];
 | 
					 | 
				
			||||||
	// Add a placeholder if specified
 | 
					 | 
				
			||||||
	if(this.editWidget.renderer.hasAttribute("placeholder")) {
 | 
					 | 
				
			||||||
		node.attributes.placeholder = {type: "string", value: this.editWidget.renderer.getAttribute("placeholder")};
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Set the element details
 | 
					 | 
				
			||||||
	this.editWidget.tag = this.editWidget.renderer.parseTreeNode.isBlock ? "div" : "span";
 | 
					 | 
				
			||||||
	this.editWidget.attributes = {
 | 
					 | 
				
			||||||
		"class": "tw-edit-texteditor"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	if(this.editWidget.renderer.hasAttribute("class")) {
 | 
					 | 
				
			||||||
		this.editWidget.attributes["class"] += " " + this.editWidget.renderer.getAttribute("class");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(this.editWidget.renderer.hasAttribute("style")) {
 | 
					 | 
				
			||||||
		this.editWidget.attributes.style = this.editWidget.attributes.style || "";
 | 
					 | 
				
			||||||
		this.editWidget.attributes.style += this.editWidget.renderer.getAttribute("style");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	this.editWidget.children = this.editWidget.renderer.renderTree.createRenderers(this.editWidget.renderer,[node]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TextEditor.prototype.setFocus = function() {
 | 
					 | 
				
			||||||
	if(this.editWidget.renderer.hasAttribute("focusSet")) {
 | 
					 | 
				
			||||||
		var title = this.editWidget.renderer.getAttribute("focusSet");
 | 
					 | 
				
			||||||
		if(this.editWidget.renderer.getAttribute("qualifyTiddlerTitles") === "yes") {
 | 
					 | 
				
			||||||
			title =  title + "-" + this.editWidget.renderer.renderTree.getContextScopeId(this.editWidget.renderer.parentRenderer);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		$tw.popup.triggerPopup({
 | 
					 | 
				
			||||||
			domNode: this.editWidget.renderer.domNode,
 | 
					 | 
				
			||||||
			title: title,
 | 
					 | 
				
			||||||
			wiki: this.editWidget.renderer.renderTree.wiki,
 | 
					 | 
				
			||||||
			force: true
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TextEditor.prototype.handleFocusEvent = function(event) {
 | 
					 | 
				
			||||||
//	this.saveChanges();
 | 
					 | 
				
			||||||
//	this.fixHeight();
 | 
					 | 
				
			||||||
	this.setFocus();
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TextEditor.prototype.handleBlurEvent = function(event) {
 | 
					 | 
				
			||||||
//	this.saveChanges();
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TextEditor.prototype.handleInputEvent = function(event) {
 | 
					 | 
				
			||||||
	this.saveChanges();
 | 
					 | 
				
			||||||
	this.fixHeight();
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TextEditor.prototype.saveChanges = function() {
 | 
					 | 
				
			||||||
	var text = this.editWidget.children[0].domNode.value
 | 
					 | 
				
			||||||
	if(this.fieldName) {
 | 
					 | 
				
			||||||
		var tiddler = this.editWidget.renderer.renderTree.wiki.getTiddler(this.tiddlerTitle);
 | 
					 | 
				
			||||||
		if(!tiddler) {
 | 
					 | 
				
			||||||
			tiddler = new $tw.Tiddler({title: this.tiddlerTitle});
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		var oldValue = tiddler.getFieldString(this.fieldName);
 | 
					 | 
				
			||||||
		if(text !== oldValue) {
 | 
					 | 
				
			||||||
			var update = {};
 | 
					 | 
				
			||||||
			update[this.fieldName] = text;
 | 
					 | 
				
			||||||
			this.editWidget.renderer.renderTree.wiki.addTiddler(new $tw.Tiddler(tiddler,update));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		var data = this.editWidget.renderer.renderTree.wiki.getTiddlerData(this.tiddlerTitle,{});
 | 
					 | 
				
			||||||
		if(data[this.indexName] !== text) {
 | 
					 | 
				
			||||||
			data[this.indexName] = text;
 | 
					 | 
				
			||||||
			this.editWidget.renderer.renderTree.wiki.setTiddlerData(this.tiddlerTitle,data);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TextEditor.prototype.fixHeight = function() {
 | 
					 | 
				
			||||||
	var self = this;
 | 
					 | 
				
			||||||
	if(this.editWidget.children[0].domNode && this.editWidget.children[0].domNode.type === "textarea") {
 | 
					 | 
				
			||||||
		$tw.utils.nextTick(function() {
 | 
					 | 
				
			||||||
			// Resize the textarea to fit its content
 | 
					 | 
				
			||||||
			var textarea = self.editWidget.children[0].domNode,
 | 
					 | 
				
			||||||
				scrollPosition = $tw.utils.getScrollPosition(),
 | 
					 | 
				
			||||||
				scrollTop = scrollPosition.y;
 | 
					 | 
				
			||||||
			// Set its height to auto so that it snaps to the correct height
 | 
					 | 
				
			||||||
			textarea.style.height = "auto";
 | 
					 | 
				
			||||||
			// Calculate the revised height
 | 
					 | 
				
			||||||
			var newHeight = Math.max(textarea.scrollHeight + textarea.offsetHeight - textarea.clientHeight,MIN_TEXT_AREA_HEIGHT);
 | 
					 | 
				
			||||||
			// Only try to change the height if it has changed
 | 
					 | 
				
			||||||
			if(newHeight !== textarea.offsetHeight) {
 | 
					 | 
				
			||||||
				textarea.style.height =  newHeight + "px";
 | 
					 | 
				
			||||||
				// Make sure that the dimensions of the textarea are recalculated
 | 
					 | 
				
			||||||
				$tw.utils.forceLayout(textarea);
 | 
					 | 
				
			||||||
				// Check that the scroll position is still visible before trying to scroll back to it
 | 
					 | 
				
			||||||
				scrollTop = Math.min(scrollTop,self.editWidget.renderer.renderTree.document.body.scrollHeight - window.innerHeight);
 | 
					 | 
				
			||||||
				window.scrollTo(scrollPosition.x,scrollTop);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TextEditor.prototype.postRenderInDom = function() {
 | 
					 | 
				
			||||||
	this.fixHeight();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TextEditor.prototype.refreshInDom = function() {
 | 
					 | 
				
			||||||
	if(this.editWidget.renderer.renderTree.document.activeElement !== this.editWidget.children[0].domNode) {
 | 
					 | 
				
			||||||
		var editInfo = this.getEditInfo();
 | 
					 | 
				
			||||||
		this.editWidget.children[0].domNode.value = editInfo.value;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Fix the height if needed
 | 
					 | 
				
			||||||
	this.fixHeight();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports["text/vnd.tiddlywiki"] = TextEditor;
 | 
					 | 
				
			||||||
exports["text/plain"] = TextEditor;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,51 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/encrypt.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Implements the encrypt widget.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var EncryptWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EncryptWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get the parameters from the attributes
 | 
					 | 
				
			||||||
	this.filter = this.renderer.getAttribute("filter");
 | 
					 | 
				
			||||||
	// Check whether we've got an encryption password
 | 
					 | 
				
			||||||
	var isEncrypted = $tw.crypto.hasPassword();
 | 
					 | 
				
			||||||
	// Encrypt the filtered tiddlers
 | 
					 | 
				
			||||||
	var tiddlers = this.renderer.renderTree.wiki.filterTiddlers(this.filter),
 | 
					 | 
				
			||||||
		json = {},
 | 
					 | 
				
			||||||
		self = this;
 | 
					 | 
				
			||||||
	$tw.utils.each(tiddlers,function(title) {
 | 
					 | 
				
			||||||
		var tiddler = self.renderer.renderTree.wiki.getTiddler(title),
 | 
					 | 
				
			||||||
			jsonTiddler = {};
 | 
					 | 
				
			||||||
		for(var f in tiddler.fields) {
 | 
					 | 
				
			||||||
			jsonTiddler[f] = tiddler.getFieldString(f);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		json[title] = jsonTiddler;
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	var encryptedText = $tw.utils.htmlEncode($tw.crypto.encrypt(JSON.stringify(json)));
 | 
					 | 
				
			||||||
	// Set the return element
 | 
					 | 
				
			||||||
	this.tag = "pre";
 | 
					 | 
				
			||||||
	this.attributes ={"class": "tw-encrypt"};
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,[{
 | 
					 | 
				
			||||||
		type: "text",
 | 
					 | 
				
			||||||
		text: encryptedText
 | 
					 | 
				
			||||||
	}]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.encrypt = EncryptWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,37 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/error.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The error widget displays an error message.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var ErrorWidget = function(renderer,errorMessage) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	this.errorMessage = errorMessage;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ErrorWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Set the element details
 | 
					 | 
				
			||||||
	this.tag = "span";
 | 
					 | 
				
			||||||
	this.attributes = {
 | 
					 | 
				
			||||||
		"class": "tw-error-widget"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,[{
 | 
					 | 
				
			||||||
			type: "text",
 | 
					 | 
				
			||||||
			text: this.errorMessage
 | 
					 | 
				
			||||||
		}]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.error = ErrorWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,87 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/fieldmangler.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The fieldmangler widget modifies the fields of the current tiddler in response to messages.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var FieldManglerWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FieldManglerWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	var self = this;
 | 
					 | 
				
			||||||
	// Get parameters from our attributes
 | 
					 | 
				
			||||||
	this.tiddlerTitle = this.renderer.getAttribute("tiddler",this.renderer.tiddlerTitle);
 | 
					 | 
				
			||||||
	// Set the element
 | 
					 | 
				
			||||||
	this.tag = "div";
 | 
					 | 
				
			||||||
	this.attributes = {
 | 
					 | 
				
			||||||
		"class": "tw-fieldmangler"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	// Set event handlers
 | 
					 | 
				
			||||||
	this.events = [
 | 
					 | 
				
			||||||
		{name: "tw-remove-field", handlerObject: this, handlerMethod: "handleRemoveFieldEvent"},
 | 
					 | 
				
			||||||
		{name: "tw-add-field", handlerObject: this, handlerMethod: "handleAddFieldEvent"},
 | 
					 | 
				
			||||||
		{name: "tw-remove-tag", handlerObject: this, handlerMethod: "handleRemoveTagEvent"},
 | 
					 | 
				
			||||||
		{name: "tw-add-tag", handlerObject: this, handlerMethod: "handleAddTagEvent"}
 | 
					 | 
				
			||||||
	];
 | 
					 | 
				
			||||||
	// Render the children
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,this.renderer.parseTreeNode.children);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FieldManglerWidget.prototype.handleRemoveFieldEvent = function(event) {
 | 
					 | 
				
			||||||
	var tiddler = this.renderer.renderTree.wiki.getTiddler(this.tiddlerTitle),
 | 
					 | 
				
			||||||
		deletion = {};
 | 
					 | 
				
			||||||
	deletion[event.param] = undefined;
 | 
					 | 
				
			||||||
	this.renderer.renderTree.wiki.addTiddler(new $tw.Tiddler(tiddler,deletion));
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FieldManglerWidget.prototype.handleAddFieldEvent = function(event) {
 | 
					 | 
				
			||||||
	var tiddler = this.renderer.renderTree.wiki.getTiddler(this.tiddlerTitle);
 | 
					 | 
				
			||||||
	if(tiddler && typeof event.param === "string" && event.param !== "" && !$tw.utils.hop(tiddler.fields,event.param)) {
 | 
					 | 
				
			||||||
		var addition = {};
 | 
					 | 
				
			||||||
		addition[event.param] = "";
 | 
					 | 
				
			||||||
		this.renderer.renderTree.wiki.addTiddler(new $tw.Tiddler(tiddler,addition));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FieldManglerWidget.prototype.handleRemoveTagEvent = function(event) {
 | 
					 | 
				
			||||||
	var tiddler = this.renderer.renderTree.wiki.getTiddler(this.tiddlerTitle);
 | 
					 | 
				
			||||||
	if(tiddler && tiddler.fields.tags) {
 | 
					 | 
				
			||||||
		var p = tiddler.fields.tags.indexOf(event.param);
 | 
					 | 
				
			||||||
		if(p !== -1) {
 | 
					 | 
				
			||||||
			var modification = {};
 | 
					 | 
				
			||||||
			modification.tags = (tiddler.fields.tags || []).slice(0);
 | 
					 | 
				
			||||||
			modification.tags.splice(p,1);
 | 
					 | 
				
			||||||
		this.renderer.renderTree.wiki.addTiddler(new $tw.Tiddler(tiddler,modification));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FieldManglerWidget.prototype.handleAddTagEvent = function(event) {
 | 
					 | 
				
			||||||
	var tiddler = this.renderer.renderTree.wiki.getTiddler(this.tiddlerTitle);
 | 
					 | 
				
			||||||
	if(tiddler && typeof event.param === "string" && event.param !== "") {
 | 
					 | 
				
			||||||
		var modification = {};
 | 
					 | 
				
			||||||
		modification.tags = (tiddler.fields.tags || []).slice(0);
 | 
					 | 
				
			||||||
		$tw.utils.pushTop(modification.tags,event.param);
 | 
					 | 
				
			||||||
		this.renderer.renderTree.wiki.addTiddler(new $tw.Tiddler(tiddler,modification));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.fieldmangler = FieldManglerWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,94 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/fields.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The fields widget displays the fields of a tiddler through a text substitution template.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var FieldsWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FieldsWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get parameters from our attributes
 | 
					 | 
				
			||||||
	this.tiddlerTitle = this.renderer.getAttribute("tiddler",this.renderer.tiddlerTitle);
 | 
					 | 
				
			||||||
	this.template = this.renderer.getAttribute("template");
 | 
					 | 
				
			||||||
	this.exclude = this.renderer.getAttribute("exclude");
 | 
					 | 
				
			||||||
	this.stripTitlePrefix = this.renderer.getAttribute("stripTitlePrefix","no") === "yes";
 | 
					 | 
				
			||||||
	// Get the tiddler we're displaying
 | 
					 | 
				
			||||||
	var tiddler = this.renderer.renderTree.wiki.getTiddler(this.tiddlerTitle);
 | 
					 | 
				
			||||||
	// Get the exclusion list
 | 
					 | 
				
			||||||
	var exclude;
 | 
					 | 
				
			||||||
	if(this.exclude) {
 | 
					 | 
				
			||||||
		exclude = this.exclude.split(" ");
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		exclude = ["text"]; 
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Compose the template
 | 
					 | 
				
			||||||
	var text = [];
 | 
					 | 
				
			||||||
	if(this.template && tiddler) {
 | 
					 | 
				
			||||||
		var fields = [];
 | 
					 | 
				
			||||||
		for(var fieldName in tiddler.fields) {
 | 
					 | 
				
			||||||
			if(exclude.indexOf(fieldName) === -1) {
 | 
					 | 
				
			||||||
				fields.push(fieldName);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		fields.sort();
 | 
					 | 
				
			||||||
		for(var f=0; f<fields.length; f++) {
 | 
					 | 
				
			||||||
			fieldName = fields[f];
 | 
					 | 
				
			||||||
			if(exclude.indexOf(fieldName) === -1) {
 | 
					 | 
				
			||||||
				var row = this.template,
 | 
					 | 
				
			||||||
					value = tiddler.getFieldString(fieldName);
 | 
					 | 
				
			||||||
				if(this.stripTitlePrefix && fieldName === "title") {
 | 
					 | 
				
			||||||
					var reStrip = /^\{[^\}]+\}(.+)/mg,
 | 
					 | 
				
			||||||
						reMatch = reStrip.exec(value);
 | 
					 | 
				
			||||||
					if(reMatch) {
 | 
					 | 
				
			||||||
						value = reMatch[1];
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				row = row.replace("$name$",fieldName);
 | 
					 | 
				
			||||||
				row = row.replace("$value$",value);
 | 
					 | 
				
			||||||
				row = row.replace("$encoded_value$",$tw.utils.htmlEncode(value));
 | 
					 | 
				
			||||||
				text.push(row)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Set the element
 | 
					 | 
				
			||||||
	this.tag = "pre";
 | 
					 | 
				
			||||||
	this.attributes = {
 | 
					 | 
				
			||||||
		"class": "tw-fields"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	// Set up the attributes for the wrapper element
 | 
					 | 
				
			||||||
	var classes = [];
 | 
					 | 
				
			||||||
	if(this.renderer.hasAttribute("class")) {
 | 
					 | 
				
			||||||
		$tw.utils.pushTop(classes,this.renderer.getAttribute("class").split(" "));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(classes.length > 0) {
 | 
					 | 
				
			||||||
		this.attributes["class"] = classes.join(" ");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(this.renderer.hasAttribute("style")) {
 | 
					 | 
				
			||||||
		this.attributes.style = this.renderer.getAttribute("style");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(this.renderer.hasAttribute("tooltip")) {
 | 
					 | 
				
			||||||
		this.attributes.title = this.renderer.getAttribute("tooltip");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Create the renderers for the wrapper and the children
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,[{
 | 
					 | 
				
			||||||
		type: "text",
 | 
					 | 
				
			||||||
		text: text.join("")
 | 
					 | 
				
			||||||
	}]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.fields = FieldsWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,109 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/grid.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The grid widget.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This example renders a table made up of tiddlers titled `MySheet_A_1`, `MySheet_A_2`, `MySheet_A_3`, ... , `MySheet_B_1`, `MySheet_B_2`, `MySheet_B_3` etc.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
<$grid prefix="MySheet" rows=20 cols=20/>
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var GridWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate widget elements
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
GridWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get our attributes
 | 
					 | 
				
			||||||
	this.prefix = this.renderer.getAttribute("prefix","Grid");
 | 
					 | 
				
			||||||
	this.rows = parseInt(this.renderer.getAttribute("rows","10"),10);
 | 
					 | 
				
			||||||
	this.cols = parseInt(this.renderer.getAttribute("cols","10"),10);
 | 
					 | 
				
			||||||
	this["class"] = this.renderer.getAttribute("class");
 | 
					 | 
				
			||||||
	// Set up the classes
 | 
					 | 
				
			||||||
	var classes = ["tw-grid-frame"];
 | 
					 | 
				
			||||||
	if(this["class"]) {
 | 
					 | 
				
			||||||
		$tw.utils.pushTop(classes,this["class"]);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Create the grid table element
 | 
					 | 
				
			||||||
	this.tag = "div";
 | 
					 | 
				
			||||||
	this.attributes = {
 | 
					 | 
				
			||||||
		"class": classes.join(" ")
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,this.generateTable());
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
GridWidget.prototype.generateTable = function() {
 | 
					 | 
				
			||||||
	var rows = [];
 | 
					 | 
				
			||||||
	for(var row=0; row<this.rows; row++) {
 | 
					 | 
				
			||||||
		var tr = {
 | 
					 | 
				
			||||||
			type: "element",
 | 
					 | 
				
			||||||
			tag: "tr",
 | 
					 | 
				
			||||||
			children: []
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
		rows.push(tr);
 | 
					 | 
				
			||||||
		for(var col=0; col<this.cols; col++) {
 | 
					 | 
				
			||||||
			var td = {
 | 
					 | 
				
			||||||
					type: "element",
 | 
					 | 
				
			||||||
					tag: "td",
 | 
					 | 
				
			||||||
					children: [{
 | 
					 | 
				
			||||||
						type: "element",
 | 
					 | 
				
			||||||
						tag: "$transclude",
 | 
					 | 
				
			||||||
						attributes: {
 | 
					 | 
				
			||||||
							title: {type: "string", value: this.getTableCellTitle(col,row)}
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}]
 | 
					 | 
				
			||||||
				};
 | 
					 | 
				
			||||||
			tr.children.push(td);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return [{
 | 
					 | 
				
			||||||
		type: "element",
 | 
					 | 
				
			||||||
		tag: "table",
 | 
					 | 
				
			||||||
		children: [{
 | 
					 | 
				
			||||||
			type: "element",
 | 
					 | 
				
			||||||
			tag: "tbody",
 | 
					 | 
				
			||||||
			children: rows
 | 
					 | 
				
			||||||
		}]
 | 
					 | 
				
			||||||
	}];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
GridWidget.prototype.getTableCellTitle = function(col,row) {
 | 
					 | 
				
			||||||
	var c = String.fromCharCode(col % 26 + "A".charCodeAt(0));
 | 
					 | 
				
			||||||
	col = Math.floor(col/26);
 | 
					 | 
				
			||||||
	while(col>0) {
 | 
					 | 
				
			||||||
		c = String.fromCharCode(col % 26 + "A".charCodeAt(0) - 1) + c;
 | 
					 | 
				
			||||||
		col = Math.floor(col/26);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return this.prefix + "_" + c + "_" + (row + 1);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
GridWidget.prototype.postRenderInDom = function() {
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
GridWidget.prototype.refreshInDom = function(changedAttributes,changedTiddlers) {
 | 
					 | 
				
			||||||
	// Reexecute the widget if any of our attributes have changed
 | 
					 | 
				
			||||||
	if(true) {
 | 
					 | 
				
			||||||
		// 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);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.grid = GridWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,256 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/import.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Implements the import widget.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
<$import>
 | 
					 | 
				
			||||||
Import using the "browse..." button or drag files onto this text
 | 
					 | 
				
			||||||
</$import>
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var ImportWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ImportWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get the parameters from the attributes
 | 
					 | 
				
			||||||
	this.browse = this.renderer.getAttribute("browse","yes");
 | 
					 | 
				
			||||||
	this["class"] = this.renderer.getAttribute("class");
 | 
					 | 
				
			||||||
	// Compute classes
 | 
					 | 
				
			||||||
	var classes = ["tw-import"];
 | 
					 | 
				
			||||||
	if(this["class"]) {
 | 
					 | 
				
			||||||
		$tw.utils.pushTop(classes,this["class"]);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Create the file input and container elements
 | 
					 | 
				
			||||||
	var fileInput = {
 | 
					 | 
				
			||||||
			type: "element",
 | 
					 | 
				
			||||||
			tag: "input",
 | 
					 | 
				
			||||||
			attributes: {
 | 
					 | 
				
			||||||
				type: {type: "string", value: "file"},
 | 
					 | 
				
			||||||
				style: {type: "string", value: this.browse === "no" ? "display: none;" : "display: block;"}
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			events: [{name: "change", handlerObject: this, handlerMethod: "handleChangeEvent"}]
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		container = {
 | 
					 | 
				
			||||||
			type: "element",
 | 
					 | 
				
			||||||
			tag: "div",
 | 
					 | 
				
			||||||
			children: this.renderer.parseTreeNode.children,
 | 
					 | 
				
			||||||
			events: [
 | 
					 | 
				
			||||||
				{name: "dragenter", handlerObject: this, handlerMethod: "handleDragEnterEvent"},
 | 
					 | 
				
			||||||
				{name: "dragover", handlerObject: this, handlerMethod: "handleDragOverEvent"},
 | 
					 | 
				
			||||||
				{name: "dragleave", handlerObject: this, handlerMethod: "handleDragLeaveEvent"},
 | 
					 | 
				
			||||||
				{name: "drop", handlerObject: this, handlerMethod: "handleDropEvent"},
 | 
					 | 
				
			||||||
				{name: "paste", handlerObject: this, handlerMethod: "handlePasteEvent"}]
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	// Set the return element
 | 
					 | 
				
			||||||
	this.tag = "div";
 | 
					 | 
				
			||||||
	this.attributes = {
 | 
					 | 
				
			||||||
		"class": classes.join(" ")
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,[fileInput,container]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ImportWidget.prototype.handleChangeEvent  = function(event) {
 | 
					 | 
				
			||||||
	event.stopPropagation();
 | 
					 | 
				
			||||||
	this.importFiles(event.target.files);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ImportWidget.prototype.handleDragEnterEvent  = function(event) {
 | 
					 | 
				
			||||||
	// We count enter/leave events
 | 
					 | 
				
			||||||
	this.dragEnterCount = (this.dragEnterCount || 0) + 1;
 | 
					 | 
				
			||||||
	// If we're entering for the first time we need to apply highlighting
 | 
					 | 
				
			||||||
	if(this.dragEnterCount === 1) {
 | 
					 | 
				
			||||||
		$tw.utils.addClass(this.renderer.domNode,"tw-dragover");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Tell the browser that we're ready to handle the drop
 | 
					 | 
				
			||||||
	event.preventDefault();
 | 
					 | 
				
			||||||
	// Tell the browser not to ripple the drag up to any parent drop handlers
 | 
					 | 
				
			||||||
	event.stopPropagation();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ImportWidget.prototype.handleDragOverEvent  = function(event) {
 | 
					 | 
				
			||||||
	// Tell the browser that we're still interested in the drop
 | 
					 | 
				
			||||||
	event.preventDefault();
 | 
					 | 
				
			||||||
	event.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ImportWidget.prototype.handleDragLeaveEvent  = function(event) {
 | 
					 | 
				
			||||||
	// Reduce the enter count
 | 
					 | 
				
			||||||
	this.dragEnterCount = (this.dragEnterCount || 0) - 1;
 | 
					 | 
				
			||||||
	// Remove highlighting if we're leaving externally
 | 
					 | 
				
			||||||
	if(this.dragEnterCount <= 0) {
 | 
					 | 
				
			||||||
		$tw.utils.removeClass(this.renderer.domNode,"tw-dragover");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ImportWidget.prototype.handleDropEvent  = function(event) {
 | 
					 | 
				
			||||||
	var dataTransfer = event.dataTransfer;
 | 
					 | 
				
			||||||
	// Reset the enter count
 | 
					 | 
				
			||||||
	this.dragEnterCount = 0;
 | 
					 | 
				
			||||||
	// Remove highlighting
 | 
					 | 
				
			||||||
	$tw.utils.removeClass(this.renderer.domNode,"tw-dragover");
 | 
					 | 
				
			||||||
	// Try to import the various data types we understand
 | 
					 | 
				
			||||||
	this.importData(dataTransfer);
 | 
					 | 
				
			||||||
	// Import any files in the drop
 | 
					 | 
				
			||||||
	this.importFiles(dataTransfer.files);
 | 
					 | 
				
			||||||
	// Tell the browser that we handled the drop
 | 
					 | 
				
			||||||
	event.preventDefault();
 | 
					 | 
				
			||||||
	// Stop the drop ripple up to any parent handlers
 | 
					 | 
				
			||||||
	event.stopPropagation();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ImportWidget.prototype.handlePasteEvent  = function(event) {
 | 
					 | 
				
			||||||
	// Let the browser handle it if we're in a textarea or input box
 | 
					 | 
				
			||||||
	if(["TEXTAREA","INPUT"].indexOf(event.target.tagName) == -1) {
 | 
					 | 
				
			||||||
		var self = this,
 | 
					 | 
				
			||||||
			items = event.clipboardData.items;
 | 
					 | 
				
			||||||
		// Enumerate the clipboard items
 | 
					 | 
				
			||||||
		for(var t = 0; t<items.length; t++) {
 | 
					 | 
				
			||||||
			var item = items[t];
 | 
					 | 
				
			||||||
			if(item.kind === "file") {
 | 
					 | 
				
			||||||
				// Import any files
 | 
					 | 
				
			||||||
				var file = item.getAsFile();
 | 
					 | 
				
			||||||
				this.importFiles([file]);
 | 
					 | 
				
			||||||
			} else if(item.kind === "string") {
 | 
					 | 
				
			||||||
				// Create tiddlers from string items
 | 
					 | 
				
			||||||
				item.getAsString(function(str) {
 | 
					 | 
				
			||||||
					var fields = {
 | 
					 | 
				
			||||||
						title: self.generateTitle("Untitled"),
 | 
					 | 
				
			||||||
						text: str
 | 
					 | 
				
			||||||
					};
 | 
					 | 
				
			||||||
					self.storeTiddler(fields);
 | 
					 | 
				
			||||||
					self.openTiddler(fields.title);
 | 
					 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// Tell the browser that we've handled the paste
 | 
					 | 
				
			||||||
		event.stopPropagation();
 | 
					 | 
				
			||||||
		event.preventDefault();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ImportWidget.prototype.openTiddler = function(title) {
 | 
					 | 
				
			||||||
	$tw.utils.dispatchCustomEvent(this.renderer.domNode,"tw-navigate",{
 | 
					 | 
				
			||||||
		navigateTo: title,
 | 
					 | 
				
			||||||
		navigateFromNode: this.renderer.domNode,
 | 
					 | 
				
			||||||
		navigateFromClientRect: this.renderer.domNode.getBoundingClientRect()
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ImportWidget.prototype.importData = function(dataTransfer) {
 | 
					 | 
				
			||||||
	for(var t=0; t<this.importDataTypes.length; t++) {
 | 
					 | 
				
			||||||
		var dataType = this.importDataTypes[t];
 | 
					 | 
				
			||||||
		var data = dataTransfer.getData(dataType.type);
 | 
					 | 
				
			||||||
		if(data !== "") {
 | 
					 | 
				
			||||||
			var fields = dataType.handler(data);
 | 
					 | 
				
			||||||
			if(!fields.title) {
 | 
					 | 
				
			||||||
				fields.title = this.generateTitle("Untitled");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			this.storeTiddler(fields);
 | 
					 | 
				
			||||||
			this.openTiddler(fields.title);
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ImportWidget.prototype.importDataTypes = [
 | 
					 | 
				
			||||||
	{type: "text/vnd.tiddler", handler: function(data) {
 | 
					 | 
				
			||||||
		return JSON.parse(data);
 | 
					 | 
				
			||||||
	}},
 | 
					 | 
				
			||||||
	{type: "text/plain", handler: function(data) {
 | 
					 | 
				
			||||||
		return {
 | 
					 | 
				
			||||||
			text: data
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	}},
 | 
					 | 
				
			||||||
	{type: "text/uri-list", handler: function(data) {
 | 
					 | 
				
			||||||
		return {
 | 
					 | 
				
			||||||
			text: data
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	}}
 | 
					 | 
				
			||||||
];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ImportWidget.prototype.importFiles = function(files) {
 | 
					 | 
				
			||||||
	var self = this,
 | 
					 | 
				
			||||||
		importFile = function(file) {
 | 
					 | 
				
			||||||
		// Get the type, falling back to the filename extension
 | 
					 | 
				
			||||||
		var type = file.type;
 | 
					 | 
				
			||||||
		if(type === "" || !type) {
 | 
					 | 
				
			||||||
			var dotPos = file.name.lastIndexOf(".");
 | 
					 | 
				
			||||||
			if(dotPos !== -1) {
 | 
					 | 
				
			||||||
				var fileExtensionInfo = $tw.config.fileExtensionInfo[file.name.substr(dotPos)];
 | 
					 | 
				
			||||||
				if(fileExtensionInfo) {
 | 
					 | 
				
			||||||
					type = fileExtensionInfo.type;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// Figure out if we're reading a binary file
 | 
					 | 
				
			||||||
		var contentTypeInfo = $tw.config.contentTypeInfo[type],
 | 
					 | 
				
			||||||
			isBinary = contentTypeInfo ? contentTypeInfo.encoding === "base64" : false;
 | 
					 | 
				
			||||||
		// Create the FileReader
 | 
					 | 
				
			||||||
		var reader = new FileReader();
 | 
					 | 
				
			||||||
		reader.onload = function(event) {
 | 
					 | 
				
			||||||
			// Deserialise the file contents
 | 
					 | 
				
			||||||
			var fields = {
 | 
					 | 
				
			||||||
				title: file.name || "Untitled",
 | 
					 | 
				
			||||||
				type: type};
 | 
					 | 
				
			||||||
			// Are we binary?
 | 
					 | 
				
			||||||
			if(isBinary) {
 | 
					 | 
				
			||||||
				var commaPos = event.target.result.indexOf(",");
 | 
					 | 
				
			||||||
				if(commaPos !== -1) {
 | 
					 | 
				
			||||||
					fields.text = event.target.result.substr(commaPos+1);
 | 
					 | 
				
			||||||
					self.storeTiddler(fields);
 | 
					 | 
				
			||||||
					self.openTiddler(fields.title);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				var tiddlers = self.renderer.renderTree.wiki.deserializeTiddlers(type,event.target.result,fields);
 | 
					 | 
				
			||||||
				if(!tiddlers) {
 | 
					 | 
				
			||||||
					console.log("No tiddlers found in file ",file.name);
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					$tw.utils.each(tiddlers,function(tiddlerFields) {
 | 
					 | 
				
			||||||
						tiddlerFields.title = self.generateTitle(tiddlerFields.title);
 | 
					 | 
				
			||||||
						self.storeTiddler(tiddlerFields);
 | 
					 | 
				
			||||||
						self.openTiddler(tiddlerFields.title);
 | 
					 | 
				
			||||||
					});
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
		if(isBinary) {
 | 
					 | 
				
			||||||
			reader.readAsDataURL(file);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			reader.readAsText(file);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	for(var f=0; f<files.length; f++) {
 | 
					 | 
				
			||||||
		importFile(files[f]);
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ImportWidget.prototype.storeTiddler = function(fields) {
 | 
					 | 
				
			||||||
	this.renderer.renderTree.wiki.addTiddler(new $tw.Tiddler(fields,this.renderer.renderTree.wiki.getModificationFields()));
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ImportWidget.prototype.generateTitle = function(baseTitle) {
 | 
					 | 
				
			||||||
	var c = 0;
 | 
					 | 
				
			||||||
	do {
 | 
					 | 
				
			||||||
		var title = baseTitle + (c ? " " + (c + 1) : "");
 | 
					 | 
				
			||||||
		c++;
 | 
					 | 
				
			||||||
	} while(this.renderer.renderTree.wiki.tiddlerExists(title));
 | 
					 | 
				
			||||||
	return title;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.import = ImportWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,115 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/info.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Implements the info widget that displays various information about a specified tiddler.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var InfoWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
InfoWidget.types = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
InfoWidget.types.changecount = function(options) {
 | 
					 | 
				
			||||||
	var text = options.wiki.getChangeCount(options.widget.renderer.tiddlerTitle);
 | 
					 | 
				
			||||||
	return [{type: "text", text: text}];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
InfoWidget.types.currentfield = function(options) {
 | 
					 | 
				
			||||||
	var fieldName = options.widget.renderer.renderTree.getContextVariable(options.widget.renderer,"field","text");
 | 
					 | 
				
			||||||
	return [{type: "text", text: fieldName}];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var FIELD_DESCRIPTION_PREFIX = "$:/docs/fields/";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
InfoWidget.types.currentfielddescription = function(options) {
 | 
					 | 
				
			||||||
	var fieldName = options.widget.renderer.renderTree.getContextVariable(options.widget.renderer,"field","text"),
 | 
					 | 
				
			||||||
		descriptionTitle = FIELD_DESCRIPTION_PREFIX + fieldName;
 | 
					 | 
				
			||||||
	return [{
 | 
					 | 
				
			||||||
		type: "element",
 | 
					 | 
				
			||||||
		tag: "$transclude",
 | 
					 | 
				
			||||||
		isBlock: false,
 | 
					 | 
				
			||||||
		attributes: {
 | 
					 | 
				
			||||||
			title: {type: "string", value: descriptionTitle}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var MODULE_TYPE_DESCRIPTION_PREFIX = "$:/docs/moduletypes/";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Return a list of all the currently loaded modules grouped by type
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
InfoWidget.types.modules = function(options) {
 | 
					 | 
				
			||||||
	var output = [],
 | 
					 | 
				
			||||||
		types = [];
 | 
					 | 
				
			||||||
	// Collect and sort the module types
 | 
					 | 
				
			||||||
	$tw.utils.each($tw.modules.types,function(moduleInfo,type) {
 | 
					 | 
				
			||||||
		types.push(type);
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	types.sort();
 | 
					 | 
				
			||||||
	// Output the module types
 | 
					 | 
				
			||||||
	$tw.utils.each(types,function(moduleType) {
 | 
					 | 
				
			||||||
		// Heading
 | 
					 | 
				
			||||||
		output.push({type: "element", tag: "h2", children: [
 | 
					 | 
				
			||||||
				{type: "text", text: moduleType}
 | 
					 | 
				
			||||||
			]})
 | 
					 | 
				
			||||||
		// Description
 | 
					 | 
				
			||||||
		output.push({
 | 
					 | 
				
			||||||
			type: "element",
 | 
					 | 
				
			||||||
			tag: "$transclude",
 | 
					 | 
				
			||||||
			isBlock: false,
 | 
					 | 
				
			||||||
			attributes: {
 | 
					 | 
				
			||||||
				title: {type: "string", value: MODULE_TYPE_DESCRIPTION_PREFIX + moduleType}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
		// List each module
 | 
					 | 
				
			||||||
		var list = {type: "element", tag: "ul", children: []},
 | 
					 | 
				
			||||||
			modules = [];
 | 
					 | 
				
			||||||
		$tw.utils.each($tw.modules.types[moduleType],function(moduleInfo,moduleName) {
 | 
					 | 
				
			||||||
			var listItem = {type: "element", tag: "li", children: [
 | 
					 | 
				
			||||||
				{type: "element", tag: "$link", attributes: {
 | 
					 | 
				
			||||||
					to: {type: "string", value: moduleName}
 | 
					 | 
				
			||||||
				}, children: [
 | 
					 | 
				
			||||||
					{type: "text", text: moduleName}
 | 
					 | 
				
			||||||
				]}
 | 
					 | 
				
			||||||
			]}
 | 
					 | 
				
			||||||
			list.children.push(listItem);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
		output.push(list);
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	return output;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
InfoWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get attributes
 | 
					 | 
				
			||||||
	this.type = this.renderer.getAttribute("type","changecount").toLowerCase();
 | 
					 | 
				
			||||||
	// Get the appropriate value for the current tiddler
 | 
					 | 
				
			||||||
	var value = [],
 | 
					 | 
				
			||||||
		fn = InfoWidget.types[this.type];
 | 
					 | 
				
			||||||
	if(fn) {
 | 
					 | 
				
			||||||
		value = fn({
 | 
					 | 
				
			||||||
			wiki: this.renderer.renderTree.wiki,
 | 
					 | 
				
			||||||
			widget: this
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Set the element
 | 
					 | 
				
			||||||
	this.tag = "span";
 | 
					 | 
				
			||||||
	this.attributes = {};
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,value);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.info = InfoWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,203 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/link.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Implements the link widget.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var isLinkExternal = function(to) {
 | 
					 | 
				
			||||||
	var externalRegExp = /(?:file|http|https|mailto|ftp|irc|news|data):[^\s'"]+(?:\/|\b)/i;
 | 
					 | 
				
			||||||
	return externalRegExp.test(to);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var LinkWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
LinkWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get the parameters from the attributes
 | 
					 | 
				
			||||||
	this.to = this.renderer.getAttribute("to",this.renderer.tiddlerTitle);
 | 
					 | 
				
			||||||
	this.hover = this.renderer.getAttribute("hover");
 | 
					 | 
				
			||||||
	this.qualifyHoverTitles = this.renderer.getAttribute("qualifyHoverTitles");
 | 
					 | 
				
			||||||
	// Qualify the hover tiddler title if needed
 | 
					 | 
				
			||||||
	if(this.qualifyHoverTitles) {
 | 
					 | 
				
			||||||
		this.hover =  this.hover + "-" + this.renderer.renderTree.getContextScopeId(this.renderer.parentRenderer);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Determine the default link characteristics
 | 
					 | 
				
			||||||
	this.isExternal = isLinkExternal(this.to);
 | 
					 | 
				
			||||||
	if(!this.isExternal) {
 | 
					 | 
				
			||||||
		this.isMissing = !this.renderer.renderTree.wiki.tiddlerExists(this.to);
 | 
					 | 
				
			||||||
		this.isShadow = this.renderer.renderTree.wiki.isShadowTiddler(this.to);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Compose the link
 | 
					 | 
				
			||||||
	var classes = ["tw-tiddlylink"]
 | 
					 | 
				
			||||||
	if(this.isExternal) {
 | 
					 | 
				
			||||||
		$tw.utils.pushTop(classes,"tw-tiddlylink-external");
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		$tw.utils.pushTop(classes,"tw-tiddlylink-internal");
 | 
					 | 
				
			||||||
		if(this.isShadow) {
 | 
					 | 
				
			||||||
			$tw.utils.pushTop(classes,"tw-tiddlylink-shadow");
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if(this.isMissing && !this.isShadow) {
 | 
					 | 
				
			||||||
			$tw.utils.pushTop(classes,"tw-tiddlylink-missing");
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			if(!this.isMissing) {
 | 
					 | 
				
			||||||
				$tw.utils.pushTop(classes,"tw-tiddlylink-resolves");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var events = [
 | 
					 | 
				
			||||||
		{name: "click", handlerObject: this, handlerMethod: "handleClickEvent"},
 | 
					 | 
				
			||||||
		{name: "dragstart", handlerObject: this, handlerMethod: "handleDragStartEvent"},
 | 
					 | 
				
			||||||
		{name: "dragend", handlerObject: this, handlerMethod: "handleDragEndEvent"}
 | 
					 | 
				
			||||||
	];
 | 
					 | 
				
			||||||
	if(this.hover) {
 | 
					 | 
				
			||||||
		events.push({name: "mouseover", handlerObject: this, handlerMethod: "handleMouseOverOrOutEvent"});
 | 
					 | 
				
			||||||
		events.push({name: "mouseout", handlerObject: this, handlerMethod: "handleMouseOverOrOutEvent"});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Get the value of the tw-wikilinks configuration macro
 | 
					 | 
				
			||||||
	var wikiLinksMacro = this.renderer.renderTree.findMacroDefinition(this.renderer.parentRenderer,"tw-wikilinks"),
 | 
					 | 
				
			||||||
		useWikiLinks = wikiLinksMacro ? !(wikiLinksMacro.text.trim() === "no") : true;
 | 
					 | 
				
			||||||
	// Set up the element
 | 
					 | 
				
			||||||
	if(useWikiLinks) {
 | 
					 | 
				
			||||||
		this.tag = "a";
 | 
					 | 
				
			||||||
		this.attributes = {
 | 
					 | 
				
			||||||
			"class": classes.join(" ")
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
		if(this.isExternal) {
 | 
					 | 
				
			||||||
			this.attributes.href = this.to;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			var wikiLinkTemplateMacro = this.renderer.renderTree.findMacroDefinition(this.renderer.parentRenderer,"tw-wikilink-template"),
 | 
					 | 
				
			||||||
				wikiLinkTemplate = wikiLinkTemplateMacro ? wikiLinkTemplateMacro.text.trim() : "#$uri_encoded$";
 | 
					 | 
				
			||||||
			this.wikiLinkText = wikiLinkTemplate.replace("$uri_encoded$",encodeURIComponent(this.to));
 | 
					 | 
				
			||||||
			this.wikiLinkText = this.wikiLinkText.replace("$uri_doubleencoded$",encodeURIComponent(encodeURIComponent(this.to)));
 | 
					 | 
				
			||||||
			this.attributes.href = this.wikiLinkText;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		this.events = events;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		this.tag = "span";
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,this.renderer.parseTreeNode.children);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
LinkWidget.prototype.handleClickEvent = function(event) {
 | 
					 | 
				
			||||||
	if(isLinkExternal(this.to)) {
 | 
					 | 
				
			||||||
		event.target.setAttribute("target","_blank");
 | 
					 | 
				
			||||||
		return true;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		var bounds = this.renderer.domNode.getBoundingClientRect();
 | 
					 | 
				
			||||||
		$tw.utils.dispatchCustomEvent(event.target,"tw-navigate",{
 | 
					 | 
				
			||||||
			navigateTo: this.to,
 | 
					 | 
				
			||||||
			navigateFromNode: this,
 | 
					 | 
				
			||||||
			navigateFromClientRect: {
 | 
					 | 
				
			||||||
				top: bounds.top,
 | 
					 | 
				
			||||||
				left: bounds.left,
 | 
					 | 
				
			||||||
				width: bounds.width,
 | 
					 | 
				
			||||||
				right: bounds.right,
 | 
					 | 
				
			||||||
				bottom: bounds.bottom,
 | 
					 | 
				
			||||||
				height: bounds.height
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
		event.preventDefault();
 | 
					 | 
				
			||||||
		event.stopPropagation();
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
LinkWidget.prototype.handleMouseOverOrOutEvent = function(event) {
 | 
					 | 
				
			||||||
	if(this.hover) {
 | 
					 | 
				
			||||||
		$tw.popup.triggerPopup({
 | 
					 | 
				
			||||||
			title: this.hover,
 | 
					 | 
				
			||||||
			domNode: this.renderer.domNode,
 | 
					 | 
				
			||||||
			wiki: this.renderer.renderTree.wiki
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	event.preventDefault();
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
LinkWidget.prototype.handleDragStartEvent = function(event) {
 | 
					 | 
				
			||||||
	if(this.to) {
 | 
					 | 
				
			||||||
		// Set the dragging class on the element being dragged
 | 
					 | 
				
			||||||
		$tw.utils.addClass(event.target,"tw-tiddlylink-dragging");
 | 
					 | 
				
			||||||
		// Create the drag image elements
 | 
					 | 
				
			||||||
		this.dragImage = this.renderer.renderTree.document.createElement("div");
 | 
					 | 
				
			||||||
		this.dragImage.className = "tw-tiddler-dragger";
 | 
					 | 
				
			||||||
		var inner = this.renderer.renderTree.document.createElement("div");
 | 
					 | 
				
			||||||
		inner.className = "tw-tiddler-dragger-inner";
 | 
					 | 
				
			||||||
		inner.appendChild(this.renderer.renderTree.document.createTextNode(this.to));
 | 
					 | 
				
			||||||
		this.dragImage.appendChild(inner);
 | 
					 | 
				
			||||||
		this.renderer.renderTree.document.body.appendChild(this.dragImage);
 | 
					 | 
				
			||||||
		// Astoundingly, we need to cover the dragger up: http://www.kryogenix.org/code/browser/custom-drag-image.html
 | 
					 | 
				
			||||||
		var bounds = this.dragImage.firstChild.getBoundingClientRect(),
 | 
					 | 
				
			||||||
			cover = this.renderer.renderTree.document.createElement("div");
 | 
					 | 
				
			||||||
		cover.className = "tw-tiddler-dragger-cover";
 | 
					 | 
				
			||||||
		cover.style.left = (bounds.left - 8) + "px";
 | 
					 | 
				
			||||||
		cover.style.top = (bounds.top - 8) + "px";
 | 
					 | 
				
			||||||
		cover.style.width = (bounds.width + 16) + "px";
 | 
					 | 
				
			||||||
		cover.style.height = (bounds.height + 16) + "px";
 | 
					 | 
				
			||||||
		this.dragImage.appendChild(cover);
 | 
					 | 
				
			||||||
		// Set the data transfer properties
 | 
					 | 
				
			||||||
		var dataTransfer = event.dataTransfer;
 | 
					 | 
				
			||||||
		dataTransfer.effectAllowed = "copy";
 | 
					 | 
				
			||||||
		dataTransfer.setDragImage(this.dragImage.firstChild,-16,-16);
 | 
					 | 
				
			||||||
		dataTransfer.clearData();
 | 
					 | 
				
			||||||
		dataTransfer.setData("text/vnd.tiddler",this.renderer.renderTree.wiki.getTiddlerAsJson(this.to));
 | 
					 | 
				
			||||||
		dataTransfer.setData("text/plain",this.renderer.renderTree.wiki.getTiddlerText(this.to,""));
 | 
					 | 
				
			||||||
		event.stopPropagation();
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		event.preventDefault();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
LinkWidget.prototype.handleDragEndEvent = function(event) {
 | 
					 | 
				
			||||||
	// Remove the dragging class on the element being dragged
 | 
					 | 
				
			||||||
	$tw.utils.removeClass(event.target,"tw-tiddlylink-dragging");
 | 
					 | 
				
			||||||
	// Delete the drag image element
 | 
					 | 
				
			||||||
	if(this.dragImage) {
 | 
					 | 
				
			||||||
		this.dragImage.parentNode.removeChild(this.dragImage);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
LinkWidget.prototype.postRenderInDom = function() {
 | 
					 | 
				
			||||||
	// Add the draggable attribute to links (we don't include it in the static HTML representation)
 | 
					 | 
				
			||||||
	if(this.renderer.domNode.tagName === "A") {
 | 
					 | 
				
			||||||
		this.renderer.domNode.setAttribute("draggable",true);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
LinkWidget.prototype.refreshInDom = function(changedAttributes,changedTiddlers) {
 | 
					 | 
				
			||||||
	// Set the class for missing tiddlers
 | 
					 | 
				
			||||||
	if(this.targetTitle && changedTiddlers[this.targetTitle]) {
 | 
					 | 
				
			||||||
		$tw.utils.toggleClass(this.renderer.domNode,"tw-tiddler-missing",!this.renderer.renderTree.wiki.tiddlerExists(this.targetTitle));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Check if any of our attributes have changed, or if a tiddler we're interested in has changed
 | 
					 | 
				
			||||||
	if(changedAttributes.to || changedAttributes.hover || (this.to && changedTiddlers[this.to]) || (this.hover && changedTiddlers[this.hover])) {
 | 
					 | 
				
			||||||
		// 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);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// We don't need to refresh ourselves, so just refresh any child nodes
 | 
					 | 
				
			||||||
		$tw.utils.each(this.children,function(node) {
 | 
					 | 
				
			||||||
			if(node.refreshInDom) {
 | 
					 | 
				
			||||||
				node.refreshInDom(changedTiddlers);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.link = LinkWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,71 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/linkcatcher.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Implements the linkcatcher widget. It intercepts navigation events from its children, preventing normal navigation, and instead stores the name of the target tiddler in the text reference specified in the `to` attribute.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Using the linkcatcher widget allows the linking mechanism to be used for tasks like selecting the current theme tiddler from a list.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var LinkCatcherWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
LinkCatcherWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get our attributes
 | 
					 | 
				
			||||||
	this.to = this.renderer.getAttribute("to");
 | 
					 | 
				
			||||||
	this.message = this.renderer.getAttribute("message");
 | 
					 | 
				
			||||||
	this.set = this.renderer.getAttribute("set");
 | 
					 | 
				
			||||||
	this.setTo = this.renderer.getAttribute("setTo");
 | 
					 | 
				
			||||||
	// Set the element
 | 
					 | 
				
			||||||
	this.tag = "div";
 | 
					 | 
				
			||||||
	this.attributes = {
 | 
					 | 
				
			||||||
		"class": "tw-linkcatcher"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,this.renderer.parseTreeNode.children);
 | 
					 | 
				
			||||||
	this.events = [
 | 
					 | 
				
			||||||
		{name: "tw-navigate", handlerObject: this, handlerMethod: "handleNavigateEvent"}
 | 
					 | 
				
			||||||
	];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
LinkCatcherWidget.prototype.refreshInDom = function(changedAttributes,changedTiddlers) {
 | 
					 | 
				
			||||||
	// We don't need to refresh ourselves, so just refresh any child nodes
 | 
					 | 
				
			||||||
	$tw.utils.each(this.children,function(node) {
 | 
					 | 
				
			||||||
		if(node.refreshInDom) {
 | 
					 | 
				
			||||||
			node.refreshInDom(changedTiddlers);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Navigate to a specified tiddler
 | 
					 | 
				
			||||||
LinkCatcherWidget.prototype.handleNavigateEvent = function(event) {
 | 
					 | 
				
			||||||
	if(this.to) {
 | 
					 | 
				
			||||||
		this.renderer.renderTree.wiki.setTextReference(this.to,event.navigateTo,this.renderer.tiddlerTitle);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(this.message) {
 | 
					 | 
				
			||||||
		$tw.utils.dispatchCustomEvent(this.renderer.domNode,this.message,{
 | 
					 | 
				
			||||||
			param: event.navigateTo,
 | 
					 | 
				
			||||||
			tiddlerTitle: this.renderer.tiddlerTitle
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(this.set) {
 | 
					 | 
				
			||||||
		var tiddler = this.renderer.renderTree.wiki.getTiddler(this.set);
 | 
					 | 
				
			||||||
		this.renderer.renderTree.wiki.addTiddler(new $tw.Tiddler(tiddler,{title: this.set, text: this.setTo}));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	event.stopPropagation();
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.linkcatcher = LinkCatcherWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,408 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/list/list.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The list widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var ListWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Initialise the listviews if they've not been done already
 | 
					 | 
				
			||||||
	if(!this.listViews) {
 | 
					 | 
				
			||||||
		ListWidget.prototype.listViews = {};
 | 
					 | 
				
			||||||
		$tw.modules.applyMethods("listview",this.listViews);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Generate widget elements
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var typeInfoByType = {
 | 
					 | 
				
			||||||
	plain: {
 | 
					 | 
				
			||||||
		frame: {
 | 
					 | 
				
			||||||
			block: "div", inline: "span"
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		member: {
 | 
					 | 
				
			||||||
			block: "div", inline: "span"
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	ul: {
 | 
					 | 
				
			||||||
		frame: {
 | 
					 | 
				
			||||||
			block: "ul", inline: "ul"
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		member: {
 | 
					 | 
				
			||||||
			block: "li", inline: "li"
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	ol: {
 | 
					 | 
				
			||||||
		frame: {
 | 
					 | 
				
			||||||
			block: "ol", inline: "ol"
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		member: {
 | 
					 | 
				
			||||||
			block: "li", inline: "li"
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ListWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get our attributes
 | 
					 | 
				
			||||||
	this.macro = this.renderer.getAttribute("macro");
 | 
					 | 
				
			||||||
	this.type = this.renderer.getAttribute("type","plain");
 | 
					 | 
				
			||||||
	this.itemClass = this.renderer.getAttribute("itemClass");
 | 
					 | 
				
			||||||
	this.template = this.renderer.getAttribute("template");
 | 
					 | 
				
			||||||
	this.editTemplate = this.renderer.getAttribute("editTemplate");
 | 
					 | 
				
			||||||
	this.emptyMessage = this.renderer.getAttribute("emptyMessage");
 | 
					 | 
				
			||||||
	this["class"] = this.renderer.getAttribute("class");
 | 
					 | 
				
			||||||
	// Get our type information
 | 
					 | 
				
			||||||
	this.typeInfo = typeInfoByType[this.type] || typeInfoByType.plain;
 | 
					 | 
				
			||||||
	// Set up the classes
 | 
					 | 
				
			||||||
	var classes = ["tw-list-frame"];
 | 
					 | 
				
			||||||
	if(this["class"]) {
 | 
					 | 
				
			||||||
		$tw.utils.pushTop(classes,this["class"]);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Get the list of tiddlers object
 | 
					 | 
				
			||||||
	this.getTiddlerList();
 | 
					 | 
				
			||||||
	// Create the list
 | 
					 | 
				
			||||||
	var listMembers = [];
 | 
					 | 
				
			||||||
	if(this.list.length === 0) {
 | 
					 | 
				
			||||||
		// Check for an empty list
 | 
					 | 
				
			||||||
		listMembers = [this.getEmptyMessage()];
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// Create the list
 | 
					 | 
				
			||||||
		for(var t=0; t<this.list.length; t++) {
 | 
					 | 
				
			||||||
			listMembers.push(this.createListElement(this.list[t]));
 | 
					 | 
				
			||||||
		}		
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Create the list frame element
 | 
					 | 
				
			||||||
	this.tag = this.renderer.parseTreeNode.isBlock ? this.typeInfo.frame.block : this.typeInfo.frame.inline;
 | 
					 | 
				
			||||||
	this.attributes = {
 | 
					 | 
				
			||||||
		"class": classes.join(" ")
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,listMembers);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ListWidget.prototype.getTiddlerList = function() {
 | 
					 | 
				
			||||||
	var filter;
 | 
					 | 
				
			||||||
	if(this.renderer.hasAttribute("filter")) {
 | 
					 | 
				
			||||||
		filter = this.renderer.getAttribute("filter");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(!filter) {
 | 
					 | 
				
			||||||
		filter = "[!is[system]]";
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	this.list = this.renderer.renderTree.wiki.filterTiddlers(filter,this.renderer.tiddlerTitle);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Create and execute the nodes representing the empty message
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
ListWidget.prototype.getEmptyMessage = function() {
 | 
					 | 
				
			||||||
	return {
 | 
					 | 
				
			||||||
		type: "element",
 | 
					 | 
				
			||||||
		tag: "span",
 | 
					 | 
				
			||||||
		children: this.renderer.renderTree.wiki.parseText("text/vnd.tiddlywiki",this.emptyMessage,{parseAsInline: true}).tree
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Create a list element representing a given tiddler
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
ListWidget.prototype.createListElement = function(title) {
 | 
					 | 
				
			||||||
	// Define an event handler that adds navigation information to the event
 | 
					 | 
				
			||||||
	var handleEvent = function(event) {
 | 
					 | 
				
			||||||
			event.navigateFromTitle = title;
 | 
					 | 
				
			||||||
			return true;
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		classes = ["tw-list-element"];
 | 
					 | 
				
			||||||
	// Add any specified classes
 | 
					 | 
				
			||||||
	if(this.itemClass) {
 | 
					 | 
				
			||||||
		$tw.utils.pushTop(classes,this.itemClass);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Return the list element
 | 
					 | 
				
			||||||
	return {
 | 
					 | 
				
			||||||
		type: "element",
 | 
					 | 
				
			||||||
		tag: this.renderer.parseTreeNode.isBlock ? this.typeInfo.member.block : this.typeInfo.member.inline,
 | 
					 | 
				
			||||||
		attributes: {
 | 
					 | 
				
			||||||
			"class": {type: "string", value: classes.join(" ")}
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		children: [this.createListElementParseTree(title)],
 | 
					 | 
				
			||||||
		events: [
 | 
					 | 
				
			||||||
			{name: "tw-navigate", handlerFunction: handleEvent},
 | 
					 | 
				
			||||||
			{name: "tw-edit-tiddler", handlerFunction: handleEvent},
 | 
					 | 
				
			||||||
			{name: "tw-save-tiddler", handlerFunction: handleEvent},
 | 
					 | 
				
			||||||
			{name: "tw-close-tiddler", handlerFunction: handleEvent},
 | 
					 | 
				
			||||||
			{name: "tw-new-tiddler", handlerFunction: handleEvent}
 | 
					 | 
				
			||||||
		]
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Create the parse tree nodes needed to represent a given list element
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
ListWidget.prototype.createListElementParseTree = function(title) {
 | 
					 | 
				
			||||||
	if(this.macro) {
 | 
					 | 
				
			||||||
		return this.createListElementMacro(title);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return this.createListElementTransclusion(title);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Create a macro call to represent a list element
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
ListWidget.prototype.createListElementMacro = function(title) {
 | 
					 | 
				
			||||||
	// Create the macrocall rendertree node
 | 
					 | 
				
			||||||
	return {
 | 
					 | 
				
			||||||
		type: "macrocall",
 | 
					 | 
				
			||||||
		name: this.macro,
 | 
					 | 
				
			||||||
		params: [
 | 
					 | 
				
			||||||
			{name: "title", value: title}
 | 
					 | 
				
			||||||
		]
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Create a transclusion to represent a list element
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
ListWidget.prototype.createListElementTransclusion = function(title) {
 | 
					 | 
				
			||||||
	// Check if the tiddler is a draft
 | 
					 | 
				
			||||||
	var tiddler = this.renderer.renderTree.wiki.getTiddler(title),
 | 
					 | 
				
			||||||
		isDraft = tiddler ? tiddler.hasField("draft.of") : false;
 | 
					 | 
				
			||||||
	// Figure out the template to use
 | 
					 | 
				
			||||||
	var template = this.template,
 | 
					 | 
				
			||||||
		templateTree = undefined;
 | 
					 | 
				
			||||||
	if(isDraft && this.editTemplate) {
 | 
					 | 
				
			||||||
		template = this.editTemplate;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Check for not having a template
 | 
					 | 
				
			||||||
	if(!template) {
 | 
					 | 
				
			||||||
		if(this.renderer.parseTreeNode.children && this.renderer.parseTreeNode.children.length > 0) {
 | 
					 | 
				
			||||||
			// Use our content as the template
 | 
					 | 
				
			||||||
			templateTree = this.renderer.parseTreeNode.children;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			// Use default content
 | 
					 | 
				
			||||||
			templateTree = [{
 | 
					 | 
				
			||||||
				type: "element",
 | 
					 | 
				
			||||||
				tag: "$view",
 | 
					 | 
				
			||||||
				attributes: {
 | 
					 | 
				
			||||||
					field: {type: "string", value: "title"},
 | 
					 | 
				
			||||||
					format: {type: "string", value: "link"}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}];
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Create the element widgets
 | 
					 | 
				
			||||||
	if(this.renderer.hasAttribute("hackTemplate")) {
 | 
					 | 
				
			||||||
		return {
 | 
					 | 
				
			||||||
			type: "element",
 | 
					 | 
				
			||||||
			tag: "$transclude",
 | 
					 | 
				
			||||||
			isBlock: this.renderer.parseTreeNode.isBlock,
 | 
					 | 
				
			||||||
			attributes: {
 | 
					 | 
				
			||||||
				title: {type: "string", value: title}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		if(!templateTree) {
 | 
					 | 
				
			||||||
			templateTree = [{
 | 
					 | 
				
			||||||
				type: "element",
 | 
					 | 
				
			||||||
				tag: "$transclude",
 | 
					 | 
				
			||||||
				attributes: {
 | 
					 | 
				
			||||||
					title: {type: "string", value: template}
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				children: templateTree
 | 
					 | 
				
			||||||
			}];
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return {
 | 
					 | 
				
			||||||
			type: "element",
 | 
					 | 
				
			||||||
			tag: "$tiddler",
 | 
					 | 
				
			||||||
			isBlock: this.renderer.parseTreeNode.isBlock,
 | 
					 | 
				
			||||||
			attributes: {
 | 
					 | 
				
			||||||
				title: {type: "string", value: title}
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			children: templateTree
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Remove a list element from the list, along with the attendant DOM nodes
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
ListWidget.prototype.removeListElement = function(index) {
 | 
					 | 
				
			||||||
	// Get the list element
 | 
					 | 
				
			||||||
	var listElement = this.children[index];
 | 
					 | 
				
			||||||
	// Invoke the listview to animate the removal
 | 
					 | 
				
			||||||
	if(this.listview && this.listview.remove) {
 | 
					 | 
				
			||||||
		if(!this.listview.remove(index)) {
 | 
					 | 
				
			||||||
			// Only delete the DOM element if the listview.remove() returned false
 | 
					 | 
				
			||||||
			listElement.domNode.parentNode.removeChild(listElement.domNode);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// Always remove the DOM node if we didn't invoke the listview
 | 
					 | 
				
			||||||
		listElement.domNode.parentNode.removeChild(listElement.domNode);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Then delete the actual renderer node
 | 
					 | 
				
			||||||
	this.children.splice(index,1);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Return the index of the list element that corresponds to a particular title
 | 
					 | 
				
			||||||
startIndex: index to start search (use zero to search from the top)
 | 
					 | 
				
			||||||
title: tiddler title to seach for
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
ListWidget.prototype.findListElementByTitle = function(startIndex,title) {
 | 
					 | 
				
			||||||
	var testNode = this.macro ? function(node) {
 | 
					 | 
				
			||||||
		// We're looking for a macro list element
 | 
					 | 
				
			||||||
		return node.widget.children[0].parseTreeNode.params[0].value === title;
 | 
					 | 
				
			||||||
	} : (this.renderer.hasAttribute("hackTemplate") ? function(node) {
 | 
					 | 
				
			||||||
			// We're looking for a transclusion list element
 | 
					 | 
				
			||||||
			return node.widget.children[0].attributes.title === title;
 | 
					 | 
				
			||||||
		} : function(node) {
 | 
					 | 
				
			||||||
			// We're looking for a transclusion list element
 | 
					 | 
				
			||||||
			return node.widget.children[0].attributes.title === title;
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	// Search for the list element
 | 
					 | 
				
			||||||
	while(startIndex < this.children.length) {
 | 
					 | 
				
			||||||
		if(testNode(this.children[startIndex])) {
 | 
					 | 
				
			||||||
			return startIndex;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		startIndex++;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return undefined;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ListWidget.prototype.postRenderInDom = function() {
 | 
					 | 
				
			||||||
	this.listview = this.chooseListView();
 | 
					 | 
				
			||||||
	this.history = [];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Select the appropriate list viewer
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
ListWidget.prototype.chooseListView = function() {
 | 
					 | 
				
			||||||
	// Instantiate the list view
 | 
					 | 
				
			||||||
	var listviewName = this.renderer.getAttribute("listview");
 | 
					 | 
				
			||||||
	var ListView = this.listViews[listviewName];
 | 
					 | 
				
			||||||
	return ListView ? new ListView(this) : null;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ListWidget.prototype.refreshInDom = function(changedAttributes,changedTiddlers) {
 | 
					 | 
				
			||||||
	// Reexecute the widget if any of our attributes have changed
 | 
					 | 
				
			||||||
	if(changedAttributes.itemClass || changedAttributes.template || changedAttributes.editTemplate || changedAttributes.emptyMessage || changedAttributes.type || changedAttributes.filter || changedAttributes.template || changedAttributes.history || changedAttributes.listview) {
 | 
					 | 
				
			||||||
		// 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);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// Handle any changes to the list, and refresh any nodes we're reusing
 | 
					 | 
				
			||||||
		this.handleListChanges(changedTiddlers);
 | 
					 | 
				
			||||||
		// Update the history list
 | 
					 | 
				
			||||||
		var history = this.renderer.getAttribute("history");
 | 
					 | 
				
			||||||
		if(history && changedTiddlers[history]) {
 | 
					 | 
				
			||||||
			this.handleHistoryChanges();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ListWidget.prototype.handleListChanges = function(changedTiddlers) {
 | 
					 | 
				
			||||||
	var t,
 | 
					 | 
				
			||||||
		prevListLength = this.list.length,
 | 
					 | 
				
			||||||
		self = this;
 | 
					 | 
				
			||||||
	// Get the list of tiddlers, having saved the previous length
 | 
					 | 
				
			||||||
	this.getTiddlerList();
 | 
					 | 
				
			||||||
	// Check if the list is empty
 | 
					 | 
				
			||||||
	if(this.list.length === 0) {
 | 
					 | 
				
			||||||
		// Check if it was empty before
 | 
					 | 
				
			||||||
		if(prevListLength === 0) {
 | 
					 | 
				
			||||||
			// If so, just refresh the empty message
 | 
					 | 
				
			||||||
			$tw.utils.each(this.children,function(node) {
 | 
					 | 
				
			||||||
				if(node.refreshInDom) {
 | 
					 | 
				
			||||||
					node.refreshInDom(changedTiddlers);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			// If the list wasn't empty before, empty it
 | 
					 | 
				
			||||||
			for(t=prevListLength-1; t>=0; t--) {
 | 
					 | 
				
			||||||
				this.removeListElement(t);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			// Insert the empty message
 | 
					 | 
				
			||||||
			this.children = this.renderer.renderTree.createRenderers(this.renderer,[this.getEmptyMessage()]);
 | 
					 | 
				
			||||||
			$tw.utils.each(this.children,function(node) {
 | 
					 | 
				
			||||||
				if(node.renderInDom) {
 | 
					 | 
				
			||||||
					self.renderer.domNode.appendChild(node.renderInDom());
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// If it is not empty now, but was empty previously, then remove the empty message
 | 
					 | 
				
			||||||
		if(prevListLength === 0) {
 | 
					 | 
				
			||||||
			this.removeListElement(0);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Step through the list and adjust our child list elements appropriately
 | 
					 | 
				
			||||||
	for(t=0; t<this.list.length; t++) {
 | 
					 | 
				
			||||||
		// Check to see if the list element is already there
 | 
					 | 
				
			||||||
		var index = this.findListElementByTitle(t,this.list[t]);
 | 
					 | 
				
			||||||
		if(index === undefined) {
 | 
					 | 
				
			||||||
			// The list element isn't there, so we need to insert it
 | 
					 | 
				
			||||||
			this.children.splice(t,0,this.renderer.renderTree.createRenderer(this.renderer,this.createListElement(this.list[t])));
 | 
					 | 
				
			||||||
			var before = this.renderer.domNode.childNodes[t],
 | 
					 | 
				
			||||||
				newNode = this.children[t].renderInDom();
 | 
					 | 
				
			||||||
			if(before) {
 | 
					 | 
				
			||||||
				this.renderer.domNode.insertBefore(newNode,before);
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				this.renderer.domNode.appendChild(newNode);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			// Ask the listview to animate the insertion
 | 
					 | 
				
			||||||
			if(this.listview && this.listview.insert) {
 | 
					 | 
				
			||||||
				this.listview.insert(t);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			// Delete any list elements preceding the one we want
 | 
					 | 
				
			||||||
			for(var n=index-1; n>=t; n--) {
 | 
					 | 
				
			||||||
				this.removeListElement(n);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			// Refresh the node we're reusing
 | 
					 | 
				
			||||||
			this.children[t].refreshInDom(changedTiddlers);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Remove any left over elements
 | 
					 | 
				
			||||||
	for(t=this.children.length-1; t>=this.list.length; t--) {
 | 
					 | 
				
			||||||
		this.removeListElement(t);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Handle any changes to the history list
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
ListWidget.prototype.handleHistoryChanges = function() {
 | 
					 | 
				
			||||||
	// Get the history data
 | 
					 | 
				
			||||||
	var historyAtt = this.renderer.getAttribute("history"),
 | 
					 | 
				
			||||||
		newHistory = this.renderer.renderTree.wiki.getTiddlerData(historyAtt,[]);
 | 
					 | 
				
			||||||
	// Ignore any entries of the history that match the previous history
 | 
					 | 
				
			||||||
	var entry = 0;
 | 
					 | 
				
			||||||
	while(entry < newHistory.length && entry < this.history.length && newHistory[entry].title === this.history[entry].title) {
 | 
					 | 
				
			||||||
		entry++;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Navigate forwards to each of the new tiddlers
 | 
					 | 
				
			||||||
	while(entry < newHistory.length) {
 | 
					 | 
				
			||||||
		if(this.listview && this.listview.navigateTo) {
 | 
					 | 
				
			||||||
			this.listview.navigateTo(newHistory[entry]);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		entry++;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Update the history
 | 
					 | 
				
			||||||
	this.history = newHistory;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.list = ListWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,100 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/list/listviews/classic.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: listview
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Views the list as a linear sequence
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var ClassicListView = function(listWidget) {
 | 
					 | 
				
			||||||
	this.listWidget = listWidget;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ClassicListView.prototype.navigateTo = function(historyInfo) {
 | 
					 | 
				
			||||||
	var listElementIndex = this.listWidget.findListElementByTitle(0,historyInfo.title);
 | 
					 | 
				
			||||||
	if(listElementIndex === undefined) {
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var listElementNode = this.listWidget.children[listElementIndex],
 | 
					 | 
				
			||||||
		targetElement = listElementNode.domNode;
 | 
					 | 
				
			||||||
	// Scroll the node into view
 | 
					 | 
				
			||||||
	var scrollEvent = this.listWidget.renderer.renderTree.document.createEvent("Event");
 | 
					 | 
				
			||||||
	scrollEvent.initEvent("tw-scroll",true,true);
 | 
					 | 
				
			||||||
	targetElement.dispatchEvent(scrollEvent);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ClassicListView.prototype.insert = function(index) {
 | 
					 | 
				
			||||||
	var listElementNode = this.listWidget.children[index],
 | 
					 | 
				
			||||||
		targetElement = listElementNode.domNode,
 | 
					 | 
				
			||||||
		duration = $tw.utils.getAnimationDuration();
 | 
					 | 
				
			||||||
	// Get the current height of the tiddler
 | 
					 | 
				
			||||||
	var currMarginBottom = parseInt(window.getComputedStyle(targetElement).marginBottom,10),
 | 
					 | 
				
			||||||
		currMarginTop = parseInt(window.getComputedStyle(targetElement).marginTop,10),
 | 
					 | 
				
			||||||
		currHeight = targetElement.offsetHeight + currMarginTop;
 | 
					 | 
				
			||||||
	// Reset the margin once the transition is over
 | 
					 | 
				
			||||||
	setTimeout(function() {
 | 
					 | 
				
			||||||
		$tw.utils.setStyle(targetElement,[
 | 
					 | 
				
			||||||
			{transition: "none"},
 | 
					 | 
				
			||||||
			{marginBottom: ""}
 | 
					 | 
				
			||||||
		]);
 | 
					 | 
				
			||||||
	},duration);
 | 
					 | 
				
			||||||
	// Set up the initial position of the element
 | 
					 | 
				
			||||||
	$tw.utils.setStyle(targetElement,[
 | 
					 | 
				
			||||||
		{transition: "none"},
 | 
					 | 
				
			||||||
		{marginBottom: (-currHeight) + "px"},
 | 
					 | 
				
			||||||
		{opacity: "0.0"}
 | 
					 | 
				
			||||||
	]);
 | 
					 | 
				
			||||||
	$tw.utils.forceLayout(targetElement);
 | 
					 | 
				
			||||||
	// Transition to the final position
 | 
					 | 
				
			||||||
	$tw.utils.setStyle(targetElement,[
 | 
					 | 
				
			||||||
		{transition: "opacity " + duration + "ms ease-in-out, " +
 | 
					 | 
				
			||||||
					"margin-bottom " + duration + "ms ease-in-out"},
 | 
					 | 
				
			||||||
		{marginBottom: currMarginBottom + "px"},
 | 
					 | 
				
			||||||
		{opacity: "1.0"}
 | 
					 | 
				
			||||||
	]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ClassicListView.prototype.remove = function(index) {
 | 
					 | 
				
			||||||
	var listElementNode = this.listWidget.children[index],
 | 
					 | 
				
			||||||
		targetElement = listElementNode.domNode,
 | 
					 | 
				
			||||||
		duration = $tw.utils.getAnimationDuration();
 | 
					 | 
				
			||||||
	// Get the current height of the tiddler
 | 
					 | 
				
			||||||
	var currWidth = targetElement.offsetWidth,
 | 
					 | 
				
			||||||
		currMarginBottom = parseInt(window.getComputedStyle(targetElement).marginBottom,10),
 | 
					 | 
				
			||||||
		currMarginTop = parseInt(window.getComputedStyle(targetElement).marginTop,10),
 | 
					 | 
				
			||||||
		currHeight = targetElement.offsetHeight + currMarginTop;
 | 
					 | 
				
			||||||
	// Remove the element at the end of the transition
 | 
					 | 
				
			||||||
	setTimeout(function() {
 | 
					 | 
				
			||||||
		if(targetElement.parentNode) {
 | 
					 | 
				
			||||||
			targetElement.parentNode.removeChild(targetElement);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},duration);
 | 
					 | 
				
			||||||
	// Animate the closure
 | 
					 | 
				
			||||||
	$tw.utils.setStyle(targetElement,[
 | 
					 | 
				
			||||||
		{transition: "none"},
 | 
					 | 
				
			||||||
		{transform: "translateX(0px)"},
 | 
					 | 
				
			||||||
		{marginBottom:  currMarginBottom + "px"},
 | 
					 | 
				
			||||||
		{opacity: "1.0"}
 | 
					 | 
				
			||||||
	]);
 | 
					 | 
				
			||||||
	$tw.utils.forceLayout(targetElement);
 | 
					 | 
				
			||||||
	$tw.utils.setStyle(targetElement,[
 | 
					 | 
				
			||||||
		{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms ease-in-out, " +
 | 
					 | 
				
			||||||
					"opacity " + duration + "ms ease-in-out, " +
 | 
					 | 
				
			||||||
					"margin-bottom " + duration + "ms ease-in-out"},
 | 
					 | 
				
			||||||
		{transform: "translateX(-" + currWidth + "px)"},
 | 
					 | 
				
			||||||
		{marginBottom: (-currHeight) + "px"},
 | 
					 | 
				
			||||||
		{opacity: "0.0"}
 | 
					 | 
				
			||||||
	]);
 | 
					 | 
				
			||||||
	// Returning true causes the DOM node not to be deleted
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.classic = ClassicListView;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,75 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/list/listviews/pop.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: listview
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Animates list insertions and removals
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var PopListView = function(listWidget) {
 | 
					 | 
				
			||||||
	this.listWidget = listWidget;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PopListView.prototype.insert = function(index) {
 | 
					 | 
				
			||||||
	var listElementNode = this.listWidget.children[index],
 | 
					 | 
				
			||||||
		targetElement = listElementNode.domNode,
 | 
					 | 
				
			||||||
		duration = $tw.utils.getAnimationDuration();
 | 
					 | 
				
			||||||
	// Reset once the transition is over
 | 
					 | 
				
			||||||
	setTimeout(function() {
 | 
					 | 
				
			||||||
		$tw.utils.setStyle(targetElement,[
 | 
					 | 
				
			||||||
			{transition: "none"},
 | 
					 | 
				
			||||||
			{transform: "none"}
 | 
					 | 
				
			||||||
		]);
 | 
					 | 
				
			||||||
	},duration);
 | 
					 | 
				
			||||||
	// Set up the initial position of the element
 | 
					 | 
				
			||||||
	$tw.utils.setStyle(targetElement,[
 | 
					 | 
				
			||||||
		{transition: "none"},
 | 
					 | 
				
			||||||
		{transform: "scale(2)"},
 | 
					 | 
				
			||||||
		{opacity: "0.0"}
 | 
					 | 
				
			||||||
	]);
 | 
					 | 
				
			||||||
	$tw.utils.forceLayout(targetElement);
 | 
					 | 
				
			||||||
	// Transition to the final position
 | 
					 | 
				
			||||||
	$tw.utils.setStyle(targetElement,[
 | 
					 | 
				
			||||||
		{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms ease-in-out, " +
 | 
					 | 
				
			||||||
					"opacity " + duration + "ms ease-in-out"},
 | 
					 | 
				
			||||||
		{transform: "scale(1)"},
 | 
					 | 
				
			||||||
		{opacity: "1.0"}
 | 
					 | 
				
			||||||
	]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PopListView.prototype.remove = function(index) {
 | 
					 | 
				
			||||||
	var listElementNode = this.listWidget.children[index],
 | 
					 | 
				
			||||||
		targetElement = listElementNode.domNode,
 | 
					 | 
				
			||||||
		duration = $tw.utils.getAnimationDuration();
 | 
					 | 
				
			||||||
	// Remove the element at the end of the transition
 | 
					 | 
				
			||||||
	setTimeout(function() {
 | 
					 | 
				
			||||||
		if(targetElement.parentNode) {
 | 
					 | 
				
			||||||
			targetElement.parentNode.removeChild(targetElement);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},duration);
 | 
					 | 
				
			||||||
	// Animate the closure
 | 
					 | 
				
			||||||
	$tw.utils.setStyle(targetElement,[
 | 
					 | 
				
			||||||
		{transition: "none"},
 | 
					 | 
				
			||||||
		{transform: "scale(1)"},
 | 
					 | 
				
			||||||
		{opacity: "1.0"}
 | 
					 | 
				
			||||||
	]);
 | 
					 | 
				
			||||||
	$tw.utils.forceLayout(targetElement);
 | 
					 | 
				
			||||||
	$tw.utils.setStyle(targetElement,[
 | 
					 | 
				
			||||||
		{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms ease-in-out, " +
 | 
					 | 
				
			||||||
					"opacity " + duration + "ms ease-in-out"},
 | 
					 | 
				
			||||||
		{transform: "scale(0.1)"},
 | 
					 | 
				
			||||||
		{opacity: "0.0"}
 | 
					 | 
				
			||||||
	]);
 | 
					 | 
				
			||||||
	// Returning true causes the DOM node not to be deleted
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.pop = PopListView;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,31 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/list/listviews/scroller.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: listview
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A list view that scrolls to newly inserted elements
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var ScrollerListView = function(listWidget) {
 | 
					 | 
				
			||||||
	this.listWidget = listWidget;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ScrollerListView.prototype.navigateTo = function(historyInfo) {
 | 
					 | 
				
			||||||
	var listElementIndex = this.listWidget.findListElementByTitle(0,historyInfo.title),
 | 
					 | 
				
			||||||
		listElementNode = this.listWidget.children[listElementIndex],
 | 
					 | 
				
			||||||
		targetElement = listElementNode.domNode;
 | 
					 | 
				
			||||||
	// Scroll the node into view
 | 
					 | 
				
			||||||
	var scrollEvent = this.listWidget.renderer.renderTree.document.createEvent("Event");
 | 
					 | 
				
			||||||
	scrollEvent.initEvent("tw-scroll",true,true);
 | 
					 | 
				
			||||||
	targetElement.dispatchEvent(scrollEvent);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.scroller = ScrollerListView;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,207 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/list/listviews/zoomin.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: listview
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Zooms between individual tiddlers
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var ZoominListView = function(listWidget) {
 | 
					 | 
				
			||||||
	this.listWidget = listWidget;
 | 
					 | 
				
			||||||
	this.storyNode = this.listWidget.renderer.domNode;
 | 
					 | 
				
			||||||
	// Set the current tiddler
 | 
					 | 
				
			||||||
	this.currentTiddler = this.listWidget.children[0].domNode;
 | 
					 | 
				
			||||||
	// Make all the tiddlers position absolute, and hide all but the first one
 | 
					 | 
				
			||||||
	this.storyNode.style.position = "relative";
 | 
					 | 
				
			||||||
	for(var t=0; t<this.storyNode.children.length; t++) {
 | 
					 | 
				
			||||||
		if(t) {
 | 
					 | 
				
			||||||
			this.storyNode.children[t].style.display = "none";
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		this.storyNode.children[t].style.position = "absolute";
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Find the first descendent node that is a <$view field="title"> widget
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
function findTitleNode(node) {
 | 
					 | 
				
			||||||
	var t,r;
 | 
					 | 
				
			||||||
	// Return true if this node is a view widget with the field attribute set to "title"
 | 
					 | 
				
			||||||
	if(node instanceof $tw.WikiRenderTree.prototype.rendererClasses.element) {
 | 
					 | 
				
			||||||
		if(node.widget instanceof $tw.WikiRenderTree.prototype.rendererClasses.element.prototype.widgetClasses.view && node.attributes.field === "title") {
 | 
					 | 
				
			||||||
			return node;	
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if(node.widget.children) {
 | 
					 | 
				
			||||||
			for(t=0; t<node.widget.children.length; t++) {
 | 
					 | 
				
			||||||
				var r = findTitleNode(node.widget.children[t]);
 | 
					 | 
				
			||||||
				if(r) {
 | 
					 | 
				
			||||||
					return r;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		if(node.children) {
 | 
					 | 
				
			||||||
			for(t=0; t<node.children.length; t++) {
 | 
					 | 
				
			||||||
				var r = findTitleNode(node.children[t]);
 | 
					 | 
				
			||||||
				if(r) {
 | 
					 | 
				
			||||||
					return r;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return null;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ZoominListView.prototype.insert = function(index) {
 | 
					 | 
				
			||||||
	var listElementNode = this.listWidget.children[index],
 | 
					 | 
				
			||||||
		targetElement = listElementNode.domNode;
 | 
					 | 
				
			||||||
	// Make the newly inserted node position absolute and hidden
 | 
					 | 
				
			||||||
	$tw.utils.setStyle(targetElement,[
 | 
					 | 
				
			||||||
		{display: "none"},
 | 
					 | 
				
			||||||
		{position: "absolute"}
 | 
					 | 
				
			||||||
	]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Visualise navigating back to the previous tiddler
 | 
					 | 
				
			||||||
	storyElement: story element being closed
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
ZoominListView.prototype.remove = function(index) {
 | 
					 | 
				
			||||||
	var listElementNode = this.listWidget.children[index],
 | 
					 | 
				
			||||||
		targetElement = listElementNode.domNode,
 | 
					 | 
				
			||||||
		duration = $tw.utils.getAnimationDuration();
 | 
					 | 
				
			||||||
	// Set up the tiddler that is being closed
 | 
					 | 
				
			||||||
	$tw.utils.setStyle(targetElement,[
 | 
					 | 
				
			||||||
		{position: "absolute"},
 | 
					 | 
				
			||||||
		{display: "block"},
 | 
					 | 
				
			||||||
		{transformOrigin: "50% 50%"},
 | 
					 | 
				
			||||||
		{transform: "translateX(0px) translateY(0px) scale(1)"},
 | 
					 | 
				
			||||||
		{transition: "none"},
 | 
					 | 
				
			||||||
		{zIndex: "0"}
 | 
					 | 
				
			||||||
	]);
 | 
					 | 
				
			||||||
	// We'll move back to the previous or next element in the story
 | 
					 | 
				
			||||||
	var toElement = this.storyNode.children[index - 1];
 | 
					 | 
				
			||||||
	if(!toElement) {
 | 
					 | 
				
			||||||
		toElement = this.storyNode.children[index + 1];
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Set up the tiddler we're moving back in
 | 
					 | 
				
			||||||
	if(toElement) {
 | 
					 | 
				
			||||||
		$tw.utils.setStyle(toElement,[
 | 
					 | 
				
			||||||
			{position: "absolute"},
 | 
					 | 
				
			||||||
			{display: "block"},
 | 
					 | 
				
			||||||
			{transformOrigin: "50% 50%"},
 | 
					 | 
				
			||||||
			{transform: "translateX(0px) translateY(0px) scale(10)"},
 | 
					 | 
				
			||||||
			{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms ease-in, opacity " + duration + "ms ease-in"},
 | 
					 | 
				
			||||||
			{opacity: "0"},
 | 
					 | 
				
			||||||
			{zIndex: "500"}
 | 
					 | 
				
			||||||
		]);
 | 
					 | 
				
			||||||
		this.currentTiddler = toElement;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Animate them both
 | 
					 | 
				
			||||||
	// Force layout
 | 
					 | 
				
			||||||
	$tw.utils.forceLayout(this.storyNode);
 | 
					 | 
				
			||||||
	// First, the tiddler we're closing
 | 
					 | 
				
			||||||
	$tw.utils.setStyle(targetElement,[
 | 
					 | 
				
			||||||
		{transformOrigin: "50% 50%"},
 | 
					 | 
				
			||||||
		{transform: "translateX(0px) translateY(0px) scale(0.1)"},
 | 
					 | 
				
			||||||
		{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms ease-in, opacity " + duration + "ms ease-in"},
 | 
					 | 
				
			||||||
		{opacity: "0"},
 | 
					 | 
				
			||||||
		{zIndex: "0"}
 | 
					 | 
				
			||||||
	]);
 | 
					 | 
				
			||||||
	setTimeout(function() {
 | 
					 | 
				
			||||||
		// Delete the DOM node when the transition is over
 | 
					 | 
				
			||||||
		if(targetElement.parentNode) {
 | 
					 | 
				
			||||||
			targetElement.parentNode.removeChild(targetElement);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},duration);
 | 
					 | 
				
			||||||
	// Now the tiddler we're going back to
 | 
					 | 
				
			||||||
	if(toElement) {
 | 
					 | 
				
			||||||
		$tw.utils.setStyle(toElement,[
 | 
					 | 
				
			||||||
			{transform: "translateX(0px) translateY(0px) scale(1)"},
 | 
					 | 
				
			||||||
			{opacity: "1"}
 | 
					 | 
				
			||||||
		]);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true; // Indicate that we'll delete the DOM node
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ZoominListView.prototype.navigateTo = function(historyInfo) {
 | 
					 | 
				
			||||||
	var listElementIndex = this.listWidget.findListElementByTitle(0,historyInfo.title),
 | 
					 | 
				
			||||||
		duration = $tw.utils.getAnimationDuration();
 | 
					 | 
				
			||||||
	if(listElementIndex === undefined) {
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var listElementNode = this.listWidget.children[listElementIndex],
 | 
					 | 
				
			||||||
		targetElement = listElementNode.domNode;
 | 
					 | 
				
			||||||
	// Make the new tiddler be position absolute and visible so that we can measure it
 | 
					 | 
				
			||||||
	$tw.utils.setStyle(targetElement,[
 | 
					 | 
				
			||||||
		{position: "absolute"},
 | 
					 | 
				
			||||||
		{display: "block"},
 | 
					 | 
				
			||||||
		{transformOrigin: "0 0"},
 | 
					 | 
				
			||||||
		{transform: "translateX(0px) translateY(0px) scale(1)"},
 | 
					 | 
				
			||||||
		{transition: "none"},
 | 
					 | 
				
			||||||
		{opacity: "0.0"}
 | 
					 | 
				
			||||||
	]);
 | 
					 | 
				
			||||||
	// Get the position of the source node, or use the centre of the window as the source position
 | 
					 | 
				
			||||||
	var sourceBounds = historyInfo.fromPageRect || {
 | 
					 | 
				
			||||||
			left: window.innerWidth/2 - 2,
 | 
					 | 
				
			||||||
			top: window.innerHeight/2 - 2,
 | 
					 | 
				
			||||||
			width: window.innerWidth/8,
 | 
					 | 
				
			||||||
			height: window.innerHeight/8
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	// Try to find the title node in the target tiddler
 | 
					 | 
				
			||||||
	var titleNode = findTitleNode(listElementNode) || listElementNode,
 | 
					 | 
				
			||||||
		zoomBounds = titleNode.domNode.getBoundingClientRect();
 | 
					 | 
				
			||||||
	// Compute the transform for the target tiddler to make the title lie over the source rectange
 | 
					 | 
				
			||||||
	var targetBounds = targetElement.getBoundingClientRect(),
 | 
					 | 
				
			||||||
		scale = sourceBounds.width / zoomBounds.width,
 | 
					 | 
				
			||||||
		x = sourceBounds.left - targetBounds.left - (zoomBounds.left - targetBounds.left) * scale,
 | 
					 | 
				
			||||||
		y = sourceBounds.top - targetBounds.top - (zoomBounds.top - targetBounds.top) * scale;
 | 
					 | 
				
			||||||
	// Transform the target tiddler to its starting position
 | 
					 | 
				
			||||||
	$tw.utils.setStyle(targetElement,[
 | 
					 | 
				
			||||||
		{transform: "translateX(" + x + "px) translateY(" + y + "px) scale(" + scale + ")"}
 | 
					 | 
				
			||||||
	]);
 | 
					 | 
				
			||||||
	// Force layout
 | 
					 | 
				
			||||||
	$tw.utils.forceLayout(targetElement);
 | 
					 | 
				
			||||||
	// Apply the ending transitions with a timeout to ensure that the previously applied transformations are applied first
 | 
					 | 
				
			||||||
	var self = this,
 | 
					 | 
				
			||||||
		prevCurrentTiddler = this.currentTiddler;
 | 
					 | 
				
			||||||
	this.currentTiddler = targetElement;
 | 
					 | 
				
			||||||
	// Transform the target tiddler to its natural size
 | 
					 | 
				
			||||||
	$tw.utils.setStyle(targetElement,[
 | 
					 | 
				
			||||||
		{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms ease-in, opacity " + duration + "ms ease-in"},
 | 
					 | 
				
			||||||
		{opacity: "1.0"},
 | 
					 | 
				
			||||||
		{transform: "translateX(0px) translateY(0px) scale(1)"},
 | 
					 | 
				
			||||||
		{zIndex: "500"},
 | 
					 | 
				
			||||||
	]);
 | 
					 | 
				
			||||||
	// Transform the previous tiddler out of the way and then hide it
 | 
					 | 
				
			||||||
	if(prevCurrentTiddler && prevCurrentTiddler !== targetElement) {
 | 
					 | 
				
			||||||
		var scale = zoomBounds.width / sourceBounds.width;
 | 
					 | 
				
			||||||
		x =  zoomBounds.left - targetBounds.left - (sourceBounds.left - targetBounds.left) * scale;
 | 
					 | 
				
			||||||
		y =  zoomBounds.top - targetBounds.top - (sourceBounds.top - targetBounds.top) * scale;
 | 
					 | 
				
			||||||
		$tw.utils.setStyle(prevCurrentTiddler,[
 | 
					 | 
				
			||||||
			{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms ease-in, opacity " + duration + "ms ease-in"},
 | 
					 | 
				
			||||||
			{opacity: "0.0"},
 | 
					 | 
				
			||||||
			{transformOrigin: "0 0"},
 | 
					 | 
				
			||||||
			{transform: "translateX(" + x + "px) translateY(" + y + "px) scale(" + scale + ")"},
 | 
					 | 
				
			||||||
			{zIndex: "0"}
 | 
					 | 
				
			||||||
		]);
 | 
					 | 
				
			||||||
		// Hide the tiddler when the transition has finished
 | 
					 | 
				
			||||||
		setTimeout(function() {
 | 
					 | 
				
			||||||
			if(self.currentTiddler !== prevCurrentTiddler) {
 | 
					 | 
				
			||||||
				prevCurrentTiddler.style.display = "none";
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		},duration);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Scroll the target into view
 | 
					 | 
				
			||||||
//	$tw.pageScroller.scrollIntoView(targetElement);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.zoomin = ZoominListView;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,301 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/navigator.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Implements the navigator widget.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var NavigatorWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NavigatorWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get our parameters
 | 
					 | 
				
			||||||
	this.storyTitle = this.renderer.getAttribute("story");
 | 
					 | 
				
			||||||
	this.historyTitle = this.renderer.getAttribute("history");
 | 
					 | 
				
			||||||
	// Set the element
 | 
					 | 
				
			||||||
	this.tag = "div";
 | 
					 | 
				
			||||||
	this.attributes = {
 | 
					 | 
				
			||||||
		"class": "tw-navigator"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,this.renderer.parseTreeNode.children);
 | 
					 | 
				
			||||||
	this.events = [
 | 
					 | 
				
			||||||
		{name: "tw-navigate", handlerObject: this, handlerMethod: "handleNavigateEvent"},
 | 
					 | 
				
			||||||
		{name: "tw-edit-tiddler", handlerObject: this, handlerMethod: "handleEditTiddlerEvent"},
 | 
					 | 
				
			||||||
		{name: "tw-delete-tiddler", handlerObject: this, handlerMethod: "handleDeleteTiddlerEvent"},
 | 
					 | 
				
			||||||
		{name: "tw-save-tiddler", handlerObject: this, handlerMethod: "handleSaveTiddlerEvent"},
 | 
					 | 
				
			||||||
		{name: "tw-cancel-tiddler", handlerObject: this, handlerMethod: "handleCancelTiddlerEvent"},
 | 
					 | 
				
			||||||
		{name: "tw-close-tiddler", handlerObject: this, handlerMethod: "handleCloseTiddlerEvent"},
 | 
					 | 
				
			||||||
		{name: "tw-close-all-tiddlers", handlerObject: this, handlerMethod: "handleCloseAllTiddlersEvent"},
 | 
					 | 
				
			||||||
		{name: "tw-new-tiddler", handlerObject: this, handlerMethod: "handleNewTiddlerEvent"}
 | 
					 | 
				
			||||||
	];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NavigatorWidget.prototype.refreshInDom = function(changedAttributes,changedTiddlers) {
 | 
					 | 
				
			||||||
	// We don't need to refresh ourselves, so just refresh any child nodes
 | 
					 | 
				
			||||||
	$tw.utils.each(this.children,function(node) {
 | 
					 | 
				
			||||||
		if(node.refreshInDom) {
 | 
					 | 
				
			||||||
			node.refreshInDom(changedTiddlers);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NavigatorWidget.prototype.getStoryList = function() {
 | 
					 | 
				
			||||||
	this.storyList = this.renderer.renderTree.wiki.getTiddlerList(this.storyTitle);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NavigatorWidget.prototype.saveStoryList = function() {
 | 
					 | 
				
			||||||
	var storyTiddler = this.renderer.renderTree.wiki.getTiddler(this.storyTitle);
 | 
					 | 
				
			||||||
	this.renderer.renderTree.wiki.addTiddler(new $tw.Tiddler({
 | 
					 | 
				
			||||||
		title: this.storyTitle
 | 
					 | 
				
			||||||
	},storyTiddler,{list: this.storyList}));
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NavigatorWidget.prototype.findTitleInStory = function(title,defaultIndex) {
 | 
					 | 
				
			||||||
	for(var t=0; t<this.storyList.length; t++) {
 | 
					 | 
				
			||||||
		if(this.storyList[t] === title) {
 | 
					 | 
				
			||||||
			return t;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}	
 | 
					 | 
				
			||||||
	return defaultIndex;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Navigate to a specified tiddler
 | 
					 | 
				
			||||||
NavigatorWidget.prototype.handleNavigateEvent = function(event) {
 | 
					 | 
				
			||||||
	if(this.storyTitle) {
 | 
					 | 
				
			||||||
		// Update the story tiddler if specified
 | 
					 | 
				
			||||||
		this.getStoryList();
 | 
					 | 
				
			||||||
		// See if the tiddler is already there
 | 
					 | 
				
			||||||
		var slot = this.findTitleInStory(event.navigateTo,-1);
 | 
					 | 
				
			||||||
		// If not we need to add it
 | 
					 | 
				
			||||||
		if(slot === -1) {
 | 
					 | 
				
			||||||
			// First we try to find the position of the story element we navigated from
 | 
					 | 
				
			||||||
			slot = this.findTitleInStory(event.navigateFromTitle,-1) + 1;
 | 
					 | 
				
			||||||
			// Add the tiddler
 | 
					 | 
				
			||||||
			this.storyList.splice(slot,0,event.navigateTo);
 | 
					 | 
				
			||||||
			// Save the story
 | 
					 | 
				
			||||||
			this.saveStoryList();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Add a new record to the top of the history stack
 | 
					 | 
				
			||||||
	if(this.historyTitle) {
 | 
					 | 
				
			||||||
		var historyList = this.renderer.renderTree.wiki.getTiddlerData(this.historyTitle,[]);
 | 
					 | 
				
			||||||
		historyList.push({title: event.navigateTo, fromPageRect: event.navigateFromClientRect});
 | 
					 | 
				
			||||||
		this.renderer.renderTree.wiki.setTiddlerData(this.historyTitle,historyList);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	event.stopPropagation();
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Close a specified tiddler
 | 
					 | 
				
			||||||
NavigatorWidget.prototype.handleCloseTiddlerEvent = function(event) {
 | 
					 | 
				
			||||||
	this.getStoryList();
 | 
					 | 
				
			||||||
	// Look for tiddlers with this title to close
 | 
					 | 
				
			||||||
	var slot = this.findTitleInStory(event.tiddlerTitle,-1);
 | 
					 | 
				
			||||||
	if(slot !== -1) {
 | 
					 | 
				
			||||||
		this.storyList.splice(slot,1);
 | 
					 | 
				
			||||||
		this.saveStoryList();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	event.stopPropagation();
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Close all tiddlers
 | 
					 | 
				
			||||||
NavigatorWidget.prototype.handleCloseAllTiddlersEvent = function(event) {
 | 
					 | 
				
			||||||
	this.storyList = [];
 | 
					 | 
				
			||||||
	this.saveStoryList();
 | 
					 | 
				
			||||||
	event.stopPropagation();
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Place a tiddler in edit mode
 | 
					 | 
				
			||||||
NavigatorWidget.prototype.handleEditTiddlerEvent = function(event) {
 | 
					 | 
				
			||||||
	this.getStoryList();
 | 
					 | 
				
			||||||
	// Replace the specified tiddler with a draft in edit mode
 | 
					 | 
				
			||||||
	for(var t=0; t<this.storyList.length; t++) {
 | 
					 | 
				
			||||||
		if(this.storyList[t] === event.tiddlerTitle) {
 | 
					 | 
				
			||||||
			// Compute the title for the draft
 | 
					 | 
				
			||||||
			var draftTitle = this.generateDraftTitle(event.tiddlerTitle);
 | 
					 | 
				
			||||||
			this.storyList[t] = draftTitle;
 | 
					 | 
				
			||||||
			// Get the current value of the tiddler we're editing
 | 
					 | 
				
			||||||
			var tiddler = this.renderer.renderTree.wiki.getTiddler(event.tiddlerTitle);
 | 
					 | 
				
			||||||
			// Save the initial value of the draft tiddler
 | 
					 | 
				
			||||||
			this.renderer.renderTree.wiki.addTiddler(new $tw.Tiddler(
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					text: "Type the text for the tiddler '" + event.tiddlerTitle + "'"
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				tiddler,
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					title: draftTitle,
 | 
					 | 
				
			||||||
					"draft.title": event.tiddlerTitle,
 | 
					 | 
				
			||||||
					"draft.of": event.tiddlerTitle
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				this.renderer.renderTree.wiki.getModificationFields()
 | 
					 | 
				
			||||||
				));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	this.saveStoryList();
 | 
					 | 
				
			||||||
	event.stopPropagation();
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Delete a tiddler
 | 
					 | 
				
			||||||
NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {
 | 
					 | 
				
			||||||
	// Get the tiddler title we're deleting
 | 
					 | 
				
			||||||
	var tiddler = this.renderer.renderTree.wiki.getTiddler(event.tiddlerTitle);
 | 
					 | 
				
			||||||
	// Check if the tiddler we're deleting is in draft mode
 | 
					 | 
				
			||||||
	if(tiddler.hasField("draft.title")) {
 | 
					 | 
				
			||||||
		// Delete the original tiddler
 | 
					 | 
				
			||||||
		this.renderer.renderTree.wiki.deleteTiddler(tiddler.fields["draft.of"]);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Delete this tiddler
 | 
					 | 
				
			||||||
	this.renderer.renderTree.wiki.deleteTiddler(event.tiddlerTitle);
 | 
					 | 
				
			||||||
	// Remove the closed tiddler from the story
 | 
					 | 
				
			||||||
	this.getStoryList();
 | 
					 | 
				
			||||||
	// Look for tiddler with this title to close
 | 
					 | 
				
			||||||
	var slot = this.findTitleInStory(event.tiddlerTitle,-1);
 | 
					 | 
				
			||||||
	if(slot !== -1) {
 | 
					 | 
				
			||||||
		this.storyList.splice(slot,1);
 | 
					 | 
				
			||||||
		this.saveStoryList();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	event.stopPropagation();
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Generate a title for the draft of a given tiddler
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
NavigatorWidget.prototype.generateDraftTitle = function(title) {
 | 
					 | 
				
			||||||
	var c = 0;
 | 
					 | 
				
			||||||
	do {
 | 
					 | 
				
			||||||
		var draftTitle = "Draft " + (c ? (c + 1) + " " : "") + "of '" + title + "'";
 | 
					 | 
				
			||||||
		c++;
 | 
					 | 
				
			||||||
	} while(this.renderer.renderTree.wiki.tiddlerExists(draftTitle));
 | 
					 | 
				
			||||||
	return draftTitle;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Take a tiddler out of edit mode, saving the changes
 | 
					 | 
				
			||||||
NavigatorWidget.prototype.handleSaveTiddlerEvent = function(event) {
 | 
					 | 
				
			||||||
	this.getStoryList();
 | 
					 | 
				
			||||||
	var storyTiddlerModified = false; // We have to special case saving the story tiddler itself
 | 
					 | 
				
			||||||
	for(var t=0; t<this.storyList.length; t++) {
 | 
					 | 
				
			||||||
		if(this.storyList[t] === event.tiddlerTitle) {
 | 
					 | 
				
			||||||
			var tiddler = this.renderer.renderTree.wiki.getTiddler(event.tiddlerTitle);
 | 
					 | 
				
			||||||
			if(tiddler) {
 | 
					 | 
				
			||||||
				var draftTitle = tiddler.fields["draft.title"],
 | 
					 | 
				
			||||||
					draftOf = tiddler.fields["draft.of"];
 | 
					 | 
				
			||||||
				if(draftTitle) {
 | 
					 | 
				
			||||||
					var isRename = draftOf !== draftTitle,
 | 
					 | 
				
			||||||
						isConfirmed = true;
 | 
					 | 
				
			||||||
					if(isRename && this.renderer.renderTree.wiki.tiddlerExists(draftTitle)) {
 | 
					 | 
				
			||||||
						isConfirmed = confirm("Do you wish to overwrite the tiddler '" + draftTitle + "'?");
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					if(isConfirmed) {
 | 
					 | 
				
			||||||
						// Save the draft tiddler as the real tiddler
 | 
					 | 
				
			||||||
						this.renderer.renderTree.wiki.addTiddler(new $tw.Tiddler(this.renderer.renderTree.wiki.getCreationFields(),tiddler,{
 | 
					 | 
				
			||||||
							title: draftTitle,
 | 
					 | 
				
			||||||
							"draft.title": undefined, 
 | 
					 | 
				
			||||||
							"draft.of": undefined
 | 
					 | 
				
			||||||
						},this.renderer.renderTree.wiki.getModificationFields()));
 | 
					 | 
				
			||||||
						// Remove the draft tiddler
 | 
					 | 
				
			||||||
						this.renderer.renderTree.wiki.deleteTiddler(event.tiddlerTitle);
 | 
					 | 
				
			||||||
						// Remove the original tiddler if we're renaming it
 | 
					 | 
				
			||||||
						if(isRename) {
 | 
					 | 
				
			||||||
							this.renderer.renderTree.wiki.deleteTiddler(draftOf);
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
						// Make the story record point to the newly saved tiddler
 | 
					 | 
				
			||||||
						this.storyList[t] = draftTitle;
 | 
					 | 
				
			||||||
						// Check if we're modifying the story tiddler itself
 | 
					 | 
				
			||||||
						if(draftTitle === this.storyTitle) {
 | 
					 | 
				
			||||||
							storyTiddlerModified = true;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(!storyTiddlerModified) {
 | 
					 | 
				
			||||||
		this.saveStoryList();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	event.stopPropagation();
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Take a tiddler out of edit mode without saving the changes
 | 
					 | 
				
			||||||
NavigatorWidget.prototype.handleCancelTiddlerEvent = function(event) {
 | 
					 | 
				
			||||||
	this.getStoryList();
 | 
					 | 
				
			||||||
	var storyTiddlerModified = false;
 | 
					 | 
				
			||||||
	for(var t=0; t<this.storyList.length; t++) {
 | 
					 | 
				
			||||||
		if(this.storyList[t] === event.tiddlerTitle) {
 | 
					 | 
				
			||||||
			var tiddler = this.renderer.renderTree.wiki.getTiddler(event.tiddlerTitle);
 | 
					 | 
				
			||||||
			if(tiddler.hasField("draft.title")) {
 | 
					 | 
				
			||||||
				// Remove the draft tiddler
 | 
					 | 
				
			||||||
				this.renderer.renderTree.wiki.deleteTiddler(event.tiddlerTitle);
 | 
					 | 
				
			||||||
				// Make the story record point to the original tiddler
 | 
					 | 
				
			||||||
				this.storyList[t] = tiddler.fields["draft.title"];
 | 
					 | 
				
			||||||
				// Check if we're modifying the story tiddler itself
 | 
					 | 
				
			||||||
				if(tiddler.fields["draft.title"] === this.storyTitle) {
 | 
					 | 
				
			||||||
					storyTiddlerModified = true;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(!storyTiddlerModified) {
 | 
					 | 
				
			||||||
		this.saveStoryList();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	event.stopPropagation();
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Create a new draft tiddler
 | 
					 | 
				
			||||||
NavigatorWidget.prototype.handleNewTiddlerEvent = function(event) {
 | 
					 | 
				
			||||||
	// Get the story details
 | 
					 | 
				
			||||||
	this.getStoryList();
 | 
					 | 
				
			||||||
	// Create the new tiddler
 | 
					 | 
				
			||||||
	var title;
 | 
					 | 
				
			||||||
	for(var t=0; true; t++) {
 | 
					 | 
				
			||||||
		title = "New Tiddler" + (t ? " " + t : "");
 | 
					 | 
				
			||||||
		if(!this.renderer.renderTree.wiki.tiddlerExists(title)) {
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var tiddler = new $tw.Tiddler(this.renderer.renderTree.wiki.getCreationFields(),{
 | 
					 | 
				
			||||||
		title: title,
 | 
					 | 
				
			||||||
		text: "Newly created tiddler"
 | 
					 | 
				
			||||||
	},this.renderer.renderTree.wiki.getModificationFields());
 | 
					 | 
				
			||||||
	this.renderer.renderTree.wiki.addTiddler(tiddler);
 | 
					 | 
				
			||||||
	// Create the draft tiddler
 | 
					 | 
				
			||||||
	var draftTitle = this.generateDraftTitle(title),
 | 
					 | 
				
			||||||
		draftTiddler = new $tw.Tiddler({
 | 
					 | 
				
			||||||
			text: "Type the text for the new tiddler",
 | 
					 | 
				
			||||||
			title: draftTitle,
 | 
					 | 
				
			||||||
			"draft.title": title,
 | 
					 | 
				
			||||||
			"draft.of": title
 | 
					 | 
				
			||||||
		},this.renderer.renderTree.wiki.getModificationFields());
 | 
					 | 
				
			||||||
	this.renderer.renderTree.wiki.addTiddler(draftTiddler);
 | 
					 | 
				
			||||||
	// Update the story to insert the new draft at the top
 | 
					 | 
				
			||||||
	var slot = this.findTitleInStory(event.navigateFromTitle,-1) + 1;
 | 
					 | 
				
			||||||
	this.storyList.splice(slot,0,draftTitle);
 | 
					 | 
				
			||||||
	// Save the updated story
 | 
					 | 
				
			||||||
	this.saveStoryList();
 | 
					 | 
				
			||||||
	// Add a new record to the top of the history stack
 | 
					 | 
				
			||||||
	var history = this.renderer.renderTree.wiki.getTiddlerData(this.historyTitle,[]);
 | 
					 | 
				
			||||||
	history.push({title: draftTitle});
 | 
					 | 
				
			||||||
	this.renderer.renderTree.wiki.setTiddlerData(this.historyTitle,history);
 | 
					 | 
				
			||||||
	event.stopPropagation();
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.navigator = NavigatorWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,45 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/password.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Implements the password widget.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var PasswordWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PasswordWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get the parameters from the attributes
 | 
					 | 
				
			||||||
	this.name = this.renderer.getAttribute("name");
 | 
					 | 
				
			||||||
	// Get the current password
 | 
					 | 
				
			||||||
	var password = $tw.browser ? $tw.utils.getPassword(this.name) : "";
 | 
					 | 
				
			||||||
	// Generate our element
 | 
					 | 
				
			||||||
	this.tag = "input";
 | 
					 | 
				
			||||||
	this.attributes = {
 | 
					 | 
				
			||||||
		type: "password",
 | 
					 | 
				
			||||||
		value: password
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	this.events = [
 | 
					 | 
				
			||||||
		{name: "keyup", handlerObject: this},
 | 
					 | 
				
			||||||
		{name: "input", handlerObject: this}];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PasswordWidget.prototype.handleEvent = function(event) {
 | 
					 | 
				
			||||||
	var password = this.renderer.domNode.value;
 | 
					 | 
				
			||||||
	return $tw.utils.savePassword(this.name,password);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.password = PasswordWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,216 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/reveal.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Implements the reveal widget.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var RevealWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RevealWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get the parameters from the attributes
 | 
					 | 
				
			||||||
	this.state = this.renderer.getAttribute("state");
 | 
					 | 
				
			||||||
	this.type = this.renderer.getAttribute("type");
 | 
					 | 
				
			||||||
	this.text = this.renderer.getAttribute("text");
 | 
					 | 
				
			||||||
	this.position = this.renderer.getAttribute("position");
 | 
					 | 
				
			||||||
	this["default"] = this.renderer.getAttribute("default","");
 | 
					 | 
				
			||||||
	this.qualifyTiddlerTitles = this.renderer.getAttribute("qualifyTiddlerTitles");
 | 
					 | 
				
			||||||
	this["class"] = this.renderer.getAttribute("class");
 | 
					 | 
				
			||||||
	this.animate = this.renderer.getAttribute("animate","no");
 | 
					 | 
				
			||||||
	// Compute the title of the state tiddler and read it
 | 
					 | 
				
			||||||
	this.stateTitle = this.state;
 | 
					 | 
				
			||||||
	if(this.qualifyTiddlerTitles) {
 | 
					 | 
				
			||||||
		this.stateTitle =  this.stateTitle + "-" + this.renderer.renderTree.getContextScopeId(this.renderer.parentRenderer);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	this.readState();
 | 
					 | 
				
			||||||
	// Set up the element attributes
 | 
					 | 
				
			||||||
	var classes = ["tw-reveal"],
 | 
					 | 
				
			||||||
		styles = [];
 | 
					 | 
				
			||||||
	if(this["class"]) {
 | 
					 | 
				
			||||||
		$tw.utils.pushTop(classes,this["class"]);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(this.isOpen) {
 | 
					 | 
				
			||||||
		$tw.utils.pushTop(classes,"tw-reveal-open");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	switch(this.type) {
 | 
					 | 
				
			||||||
		case "popup":
 | 
					 | 
				
			||||||
			styles.push("position:absolute;");
 | 
					 | 
				
			||||||
			classes.push("tw-popup");
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	styles.push("display:" + (this.isOpen ? (this.renderer.parseTreeNode.isBlock ? "block" : "inline") : "none") + ";");
 | 
					 | 
				
			||||||
	// Set the element
 | 
					 | 
				
			||||||
	this.tag =  "div";
 | 
					 | 
				
			||||||
	this.attributes = {
 | 
					 | 
				
			||||||
		"class": classes.join(" "),
 | 
					 | 
				
			||||||
		style: styles.join("")
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,this.isOpen ? this.renderer.parseTreeNode.children : []);
 | 
					 | 
				
			||||||
	this.events = [{name: "click", handlerObject: this, handlerMethod: "handleClickEvent"}];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Read the state tiddler
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
RevealWidget.prototype.readState = function() {
 | 
					 | 
				
			||||||
	// Read the information from the state tiddler
 | 
					 | 
				
			||||||
	if(this.stateTitle) {
 | 
					 | 
				
			||||||
		var state = this.renderer.renderTree.wiki.getTextReference(this.stateTitle,this["default"],this.renderer.tiddlerTitle);
 | 
					 | 
				
			||||||
		switch(this.type) {
 | 
					 | 
				
			||||||
			case "popup":
 | 
					 | 
				
			||||||
				this.readPopupState(state);
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case "match":
 | 
					 | 
				
			||||||
				this.readMatchState(state);
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case "nomatch":
 | 
					 | 
				
			||||||
				this.readMatchState(state);
 | 
					 | 
				
			||||||
				this.isOpen = !this.isOpen;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RevealWidget.prototype.readMatchState = function(state) {
 | 
					 | 
				
			||||||
	this.isOpen = state === this.text;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RevealWidget.prototype.readPopupState = function(state) {
 | 
					 | 
				
			||||||
	var popupLocationRegExp = /^\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/,
 | 
					 | 
				
			||||||
		match = popupLocationRegExp.exec(state);
 | 
					 | 
				
			||||||
	// Check if the state matches the location regexp
 | 
					 | 
				
			||||||
	if(match) {
 | 
					 | 
				
			||||||
		// If so, we're open
 | 
					 | 
				
			||||||
		this.isOpen = true;
 | 
					 | 
				
			||||||
		// Get the location
 | 
					 | 
				
			||||||
		this.popup = {
 | 
					 | 
				
			||||||
			left: parseFloat(match[1]),
 | 
					 | 
				
			||||||
			top: parseFloat(match[2]),
 | 
					 | 
				
			||||||
			width: parseFloat(match[3]),
 | 
					 | 
				
			||||||
			height: parseFloat(match[4])
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// If not, we're closed
 | 
					 | 
				
			||||||
		this.isOpen = false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RevealWidget.prototype.handleClickEvent = function(event) {
 | 
					 | 
				
			||||||
	if(event.type === "click" && this.type === "popup") {
 | 
					 | 
				
			||||||
		// Cancel the popup if we get a click on it
 | 
					 | 
				
			||||||
		if(this.stateTitle) {
 | 
					 | 
				
			||||||
			this.renderer.renderTree.wiki.deleteTextReference(this.stateTitle);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		event.preventDefault();
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RevealWidget.prototype.refreshInDom = function(changedAttributes,changedTiddlers) {
 | 
					 | 
				
			||||||
	var self = this;
 | 
					 | 
				
			||||||
	// Check if any of our attributes have changed, or if a tiddler we're interested in has changed
 | 
					 | 
				
			||||||
	if(changedAttributes.state || changedAttributes.type || changedAttributes.text || changedAttributes.position || changedAttributes["default"] || changedAttributes.qualifyTiddlerTitles || changedAttributes["class"]) {
 | 
					 | 
				
			||||||
		// 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);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		var needChildrenRefresh = true; // Avoid refreshing the children nodes if we don't need to
 | 
					 | 
				
			||||||
		// Get the open state
 | 
					 | 
				
			||||||
		var previousState = this.isOpen
 | 
					 | 
				
			||||||
		this.readState();
 | 
					 | 
				
			||||||
		// Construct the child nodes if  required
 | 
					 | 
				
			||||||
		if(this.isOpen && this.children.length === 0) {
 | 
					 | 
				
			||||||
			this.children = this.renderer.renderTree.createRenderers(this.renderer,this.renderer.parseTreeNode.children);
 | 
					 | 
				
			||||||
			var parentNode = this.renderer.domNode;
 | 
					 | 
				
			||||||
			$tw.utils.each(this.children,function(child) {
 | 
					 | 
				
			||||||
				parentNode.appendChild(child.renderInDom());
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
			needChildrenRefresh = false;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// Refresh any child nodes
 | 
					 | 
				
			||||||
		if(needChildrenRefresh) {
 | 
					 | 
				
			||||||
			$tw.utils.each(this.children,function(node) {
 | 
					 | 
				
			||||||
				if(node.refreshInDom) {
 | 
					 | 
				
			||||||
					node.refreshInDom(changedTiddlers);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// Animate the opening or closing
 | 
					 | 
				
			||||||
		if(this.isOpen !== previousState) {
 | 
					 | 
				
			||||||
			if(this.animate !== "no") {
 | 
					 | 
				
			||||||
				if(this.isOpen) {
 | 
					 | 
				
			||||||
					this.renderer.domNode.style.display = this.renderer.parseTreeNode.isBlock ? "block" : "inline";
 | 
					 | 
				
			||||||
					$tw.anim.perform("open",this.renderer.domNode);
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					$tw.anim.perform("close",this.renderer.domNode,{callback: function() {
 | 
					 | 
				
			||||||
						self.renderer.domNode.style.display = "none";
 | 
					 | 
				
			||||||
					}});
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				this.renderer.domNode.style.display = this.isOpen ? (this.renderer.parseTreeNode.isBlock ? "block" : "inline") : "none";
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// Add or remove the tw-reveal-open class
 | 
					 | 
				
			||||||
		$tw.utils.toggleClass(this.renderer.domNode,"tw-reveal-open",this.isOpen);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Position the content if required
 | 
					 | 
				
			||||||
	if(this.isOpen) {
 | 
					 | 
				
			||||||
		this.postRenderInDom();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RevealWidget.prototype.postRenderInDom = function() {
 | 
					 | 
				
			||||||
	switch(this.type) {
 | 
					 | 
				
			||||||
		case "popup":
 | 
					 | 
				
			||||||
			if(this.isOpen) {
 | 
					 | 
				
			||||||
				this.renderer.domNode.style.position = "absolute";
 | 
					 | 
				
			||||||
				this.renderer.domNode.style.zIndex = "1000";
 | 
					 | 
				
			||||||
				switch(this.position) {
 | 
					 | 
				
			||||||
					case "left":
 | 
					 | 
				
			||||||
						this.renderer.domNode.style.left = (this.popup.left - this.renderer.domNode.offsetWidth) + "px";
 | 
					 | 
				
			||||||
						this.renderer.domNode.style.top = this.popup.top + "px";
 | 
					 | 
				
			||||||
						break;
 | 
					 | 
				
			||||||
					case "above":
 | 
					 | 
				
			||||||
						this.renderer.domNode.style.left = this.popup.left + "px";
 | 
					 | 
				
			||||||
						this.renderer.domNode.style.top = (this.popup.top - this.renderer.domNode.offsetHeight) + "px";
 | 
					 | 
				
			||||||
						break;
 | 
					 | 
				
			||||||
					case "aboveright":
 | 
					 | 
				
			||||||
						this.renderer.domNode.style.left = (this.popup.left + this.popup.width) + "px";
 | 
					 | 
				
			||||||
						this.renderer.domNode.style.top = (this.popup.top + this.popup.height - this.renderer.domNode.offsetHeight) + "px";
 | 
					 | 
				
			||||||
						break;
 | 
					 | 
				
			||||||
					case "right":
 | 
					 | 
				
			||||||
						this.renderer.domNode.style.left = (this.popup.left + this.popup.width) + "px";
 | 
					 | 
				
			||||||
						this.renderer.domNode.style.top = this.popup.top + "px";
 | 
					 | 
				
			||||||
						break;
 | 
					 | 
				
			||||||
					case "belowleft":
 | 
					 | 
				
			||||||
						this.renderer.domNode.style.left = (this.popup.left + this.popup.width - this.renderer.domNode.offsetWidth) + "px";
 | 
					 | 
				
			||||||
						this.renderer.domNode.style.top = (this.popup.top + this.popup.height) + "px";
 | 
					 | 
				
			||||||
						break;
 | 
					 | 
				
			||||||
					default: // Below
 | 
					 | 
				
			||||||
						this.renderer.domNode.style.left = this.popup.left + "px";
 | 
					 | 
				
			||||||
						this.renderer.domNode.style.top = (this.popup.top + this.popup.height) + "px";
 | 
					 | 
				
			||||||
						break;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.reveal = RevealWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,58 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/setstyle.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Implements the setstyle widget.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var SetStyleWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SetStyleWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get the parameters from the attributes
 | 
					 | 
				
			||||||
	this.name = this.renderer.getAttribute("name");
 | 
					 | 
				
			||||||
	this.value = this.renderer.getAttribute("value");
 | 
					 | 
				
			||||||
	this["class"] = this.renderer.getAttribute("class");
 | 
					 | 
				
			||||||
	// Set up the element
 | 
					 | 
				
			||||||
	this.tag = this.renderer.parseTreeNode.isBlock ? "div" : "span";
 | 
					 | 
				
			||||||
	this.attributes = {
 | 
					 | 
				
			||||||
		style: this.name + ":" + this.value
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	if(this["class"]) {
 | 
					 | 
				
			||||||
		this.attributes["class"] = this["class"];
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,this.renderer.parseTreeNode.children);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SetStyleWidget.prototype.refreshInDom = function(changedAttributes,changedTiddlers) {
 | 
					 | 
				
			||||||
	// Check if any of our attributes have changed, or if a tiddler we're interested in has changed
 | 
					 | 
				
			||||||
	if(changedAttributes.name || changedAttributes.value || changedAttributes["class"]) {
 | 
					 | 
				
			||||||
		// 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);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// We don't need to refresh ourselves, so just refresh any child nodes
 | 
					 | 
				
			||||||
		$tw.utils.each(this.children,function(node) {
 | 
					 | 
				
			||||||
			if(node.refreshInDom) {
 | 
					 | 
				
			||||||
				node.refreshInDom(changedTiddlers);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.setstyle = SetStyleWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,82 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/tiddler.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The tiddler widget sets the current tiddler to a specified title.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Attributes:
 | 
					 | 
				
			||||||
	title: the title of the current tiddler
 | 
					 | 
				
			||||||
	class: CSS classes
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var TiddlerWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TiddlerWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	var self = this;
 | 
					 | 
				
			||||||
	this.tiddlerTitle = this.renderer.getAttribute("title","");
 | 
					 | 
				
			||||||
	// Set up the attributes for the wrapper element
 | 
					 | 
				
			||||||
	var classes = ["tw-tiddler"];
 | 
					 | 
				
			||||||
	if(this.renderer.hasAttribute("class")) {
 | 
					 | 
				
			||||||
		$tw.utils.pushTop(classes,this.renderer.getAttribute("class").split(" "));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(!this.renderer.renderTree.wiki.tiddlerExists(this.tiddlerTitle) && !this.renderer.renderTree.wiki.isShadowTiddler(this.tiddlerTitle)) {
 | 
					 | 
				
			||||||
		$tw.utils.pushTop(classes,"tw-tiddler-missing");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Save the context for this renderer node
 | 
					 | 
				
			||||||
	this.renderer.context = {
 | 
					 | 
				
			||||||
		tiddlerTitle: this.tiddlerTitle
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	// Initialise events
 | 
					 | 
				
			||||||
	this.events = [];
 | 
					 | 
				
			||||||
	// Trap and update tag modification events
 | 
					 | 
				
			||||||
	this.events.push({name: "tw-remove-tag", handlerFunction: function(event) {
 | 
					 | 
				
			||||||
		event.currentTag = self.tiddlerTitle;
 | 
					 | 
				
			||||||
		return true;
 | 
					 | 
				
			||||||
	}});
 | 
					 | 
				
			||||||
	// Set the element
 | 
					 | 
				
			||||||
	this.tag = this.renderer.parseTreeNode.isBlock ? "div" : "span";
 | 
					 | 
				
			||||||
	this.attributes = {};
 | 
					 | 
				
			||||||
	if(classes.length > 0) {
 | 
					 | 
				
			||||||
		this.attributes["class"] = classes.join(" ");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,this.renderer.parseTreeNode.children);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TiddlerWidget.prototype.refreshInDom = function(changedAttributes,changedTiddlers) {
 | 
					 | 
				
			||||||
	// Set the class for missing tiddlers
 | 
					 | 
				
			||||||
	if(this.tiddlerTitle && changedTiddlers[this.tiddlerTitle]) {
 | 
					 | 
				
			||||||
		$tw.utils.toggleClass(this.renderer.domNode,"tw-tiddler-missing",!this.renderer.renderTree.wiki.tiddlerExists(this.tiddlerTitle));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Check if any of our attributes have changed, or if a tiddler we're interested in has changed
 | 
					 | 
				
			||||||
	if(changedAttributes.title) {
 | 
					 | 
				
			||||||
		// 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);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// We don't need to refresh ourselves, so just refresh any child nodes
 | 
					 | 
				
			||||||
		$tw.utils.each(this.children,function(node) {
 | 
					 | 
				
			||||||
			if(node.refreshInDom) {
 | 
					 | 
				
			||||||
				node.refreshInDom(changedTiddlers);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.tiddler = TiddlerWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,105 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/transclude.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The transclude widget includes another tiddler into the tiddler being rendered.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Attributes:
 | 
					 | 
				
			||||||
	title: the title of the tiddler to transclude
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var TranscludeWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TranscludeWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	var self = this,
 | 
					 | 
				
			||||||
		templateParseTree;
 | 
					 | 
				
			||||||
	// Get the render target details
 | 
					 | 
				
			||||||
	this.transcludeTitle = this.renderer.getAttribute("title",this.renderer.tiddlerTitle);
 | 
					 | 
				
			||||||
	this.transcludeField = this.renderer.getAttribute("field");
 | 
					 | 
				
			||||||
	this.transcludeIndex = this.renderer.getAttribute("index");
 | 
					 | 
				
			||||||
	// Check for recursion
 | 
					 | 
				
			||||||
	if(this.renderer.renderTree.checkContextRecursion(this.renderer.parentRenderer,{
 | 
					 | 
				
			||||||
			transcludeTitle: this.transcludeTitle,
 | 
					 | 
				
			||||||
			transcludeField: this.transcludeField,
 | 
					 | 
				
			||||||
			transcludeIndex: this.transcludeIndex
 | 
					 | 
				
			||||||
		})) {
 | 
					 | 
				
			||||||
		templateParseTree = [{type: "text", text: "Tiddler recursion error in transclude widget"}];	
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		var parser;
 | 
					 | 
				
			||||||
		if(this.transcludeField === "text" || (!this.transcludeField && !this.transcludeIndex)) {
 | 
					 | 
				
			||||||
			parser = this.renderer.renderTree.wiki.parseTiddler(this.transcludeTitle,{parseAsInline: !this.renderer.parseTreeNode.isBlock});
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			var tiddler,text;
 | 
					 | 
				
			||||||
			if(this.transcludeField) {
 | 
					 | 
				
			||||||
				tiddler = this.renderer.renderTree.wiki.getTiddler(this.transcludeTitle);
 | 
					 | 
				
			||||||
				text = tiddler ? tiddler.fields[this.transcludeField] : "";
 | 
					 | 
				
			||||||
				if(text === undefined) {
 | 
					 | 
				
			||||||
					text = "";
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				parser = this.renderer.renderTree.wiki.parseText("text/vnd.tiddlywiki",text,{parseAsInline: !this.renderer.parseTreeNode.isBlock});
 | 
					 | 
				
			||||||
			} else if(this.transcludeIndex) {
 | 
					 | 
				
			||||||
				text = this.renderer.renderTree.wiki.extractTiddlerDataItem(this.transcludeTitle,this.transcludeIndex,"");
 | 
					 | 
				
			||||||
				parser = this.renderer.renderTree.wiki.parseText("text/vnd.tiddlywiki",text,{parseAsInline: !this.renderer.parseTreeNode.isBlock});
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		templateParseTree = parser ? parser.tree : [];
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Set up the attributes for the wrapper element
 | 
					 | 
				
			||||||
	var classes = ["tw-transclude"];
 | 
					 | 
				
			||||||
	if(this.renderer.hasAttribute("class")) {
 | 
					 | 
				
			||||||
		$tw.utils.pushTop(classes,this.renderer.getAttribute("class").split(" "));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Save the context for this renderer node
 | 
					 | 
				
			||||||
	this.renderer.context = {
 | 
					 | 
				
			||||||
		transcludeTitle: this.transcludeTitle,
 | 
					 | 
				
			||||||
		transcludeField: this.transcludeField,
 | 
					 | 
				
			||||||
		transcludeIndex: this.transcludeIndex
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	// Set the element
 | 
					 | 
				
			||||||
	this.tag = this.renderer.parseTreeNode.isBlock ? "div" : "span";
 | 
					 | 
				
			||||||
	this.attributes = {};
 | 
					 | 
				
			||||||
	if(classes.length > 0) {
 | 
					 | 
				
			||||||
		this.attributes["class"] = classes.join(" ");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(this.renderer.hasAttribute("style")) {
 | 
					 | 
				
			||||||
		this.attributes.style = this.renderer.getAttribute("style");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(this.renderer.hasAttribute("tooltip")) {
 | 
					 | 
				
			||||||
		this.attributes.title = this.renderer.getAttribute("tooltip");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,templateParseTree);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TranscludeWidget.prototype.refreshInDom = function(changedAttributes,changedTiddlers) {
 | 
					 | 
				
			||||||
	// Check if any of our attributes have changed, or if a tiddler we're interested in has changed
 | 
					 | 
				
			||||||
	if(changedAttributes.transcludeField || changedAttributes.transcludeIndex || (this.transcludeTitle && changedTiddlers[this.transcludeTitle])) {
 | 
					 | 
				
			||||||
		// 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);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// We don't need to refresh ourselves, so just refresh any child nodes
 | 
					 | 
				
			||||||
		$tw.utils.each(this.children,function(node) {
 | 
					 | 
				
			||||||
			if(node.refreshInDom) {
 | 
					 | 
				
			||||||
				node.refreshInDom(changedTiddlers);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.transclude = TranscludeWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,34 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/version.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Implements the version widget.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var VersionWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
VersionWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Set the element
 | 
					 | 
				
			||||||
	this.tag = "span";
 | 
					 | 
				
			||||||
	this.attributes = {};
 | 
					 | 
				
			||||||
	this.children = this.renderer.renderTree.createRenderers(this.renderer,[{
 | 
					 | 
				
			||||||
		type: "text",
 | 
					 | 
				
			||||||
		text: $tw.version
 | 
					 | 
				
			||||||
	}]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.version = VersionWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,70 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/video.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Implements the video widget.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var VideoWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
VideoWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get attributes
 | 
					 | 
				
			||||||
	this.src = this.renderer.getAttribute("src");
 | 
					 | 
				
			||||||
	this.type = this.renderer.getAttribute("type","vimeo");
 | 
					 | 
				
			||||||
	this.width = parseInt(this.renderer.getAttribute("width","640"),10);
 | 
					 | 
				
			||||||
	this.height = parseInt(this.renderer.getAttribute("height","360"),10);
 | 
					 | 
				
			||||||
	// Return the appropriate element
 | 
					 | 
				
			||||||
	switch(this.type) {
 | 
					 | 
				
			||||||
		case "vimeo":
 | 
					 | 
				
			||||||
			this.tag = "iframe";
 | 
					 | 
				
			||||||
			this.attributes = {
 | 
					 | 
				
			||||||
				src: "http://player.vimeo.com/video/" + this.src + "?autoplay=0",
 | 
					 | 
				
			||||||
				width: this.width,
 | 
					 | 
				
			||||||
				height: this.height,
 | 
					 | 
				
			||||||
				frameborder: 0
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case "youtube":
 | 
					 | 
				
			||||||
			this.tag = "iframe";
 | 
					 | 
				
			||||||
			this.attributes = {
 | 
					 | 
				
			||||||
				src: "http://www.youtube.com/embed/" + this.src,
 | 
					 | 
				
			||||||
				width: this.width,
 | 
					 | 
				
			||||||
				height: this.height,
 | 
					 | 
				
			||||||
				frameborder: 0
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case "archiveorg":
 | 
					 | 
				
			||||||
			this.tag = "iframe";
 | 
					 | 
				
			||||||
			this.attributes = {
 | 
					 | 
				
			||||||
				src: "http://www.archive.org/embed/" + this.src,
 | 
					 | 
				
			||||||
				width: this.width,
 | 
					 | 
				
			||||||
				height: this.height,
 | 
					 | 
				
			||||||
				frameborder: 0
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			this.tag = "div";
 | 
					 | 
				
			||||||
			this.attributes = {};
 | 
					 | 
				
			||||||
			this.children = this.renderer.renderTree.createRenderers(this.renderer,[{
 | 
					 | 
				
			||||||
				type: "text",
 | 
					 | 
				
			||||||
				text: "Unknown video type"
 | 
					 | 
				
			||||||
			}]);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.video = VideoWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,120 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/view.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: widget
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The view widget displays a tiddler field.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Define the "text" viewer here so that it is always available
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
var TextViewer = function(viewWidget,tiddler,field,value) {
 | 
					 | 
				
			||||||
	this.viewWidget = viewWidget;
 | 
					 | 
				
			||||||
	this.tiddler = tiddler;
 | 
					 | 
				
			||||||
	this.field = field;
 | 
					 | 
				
			||||||
	this.value = value;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TextViewer.prototype.render = function() {
 | 
					 | 
				
			||||||
	// Get the value as a string
 | 
					 | 
				
			||||||
	if(this.field !== "text" && this.tiddler) {
 | 
					 | 
				
			||||||
		this.value = this.tiddler.getFieldString(this.field);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var value = "";
 | 
					 | 
				
			||||||
	if(this.value !== undefined && this.value !== null) {
 | 
					 | 
				
			||||||
		value = this.value;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Set the element details
 | 
					 | 
				
			||||||
	this.viewWidget.tag = "span";
 | 
					 | 
				
			||||||
	this.viewWidget.attributes = {};
 | 
					 | 
				
			||||||
	this.viewWidget.children = this.viewWidget.renderer.renderTree.createRenderers(this.viewWidget.renderer.renderContext,[{
 | 
					 | 
				
			||||||
		type: "text",
 | 
					 | 
				
			||||||
		text: value
 | 
					 | 
				
			||||||
	}]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var ViewWidget = function(renderer) {
 | 
					 | 
				
			||||||
	// Save state
 | 
					 | 
				
			||||||
	this.renderer = renderer;
 | 
					 | 
				
			||||||
	// Initialise the field viewers if they've not been done already
 | 
					 | 
				
			||||||
	if(!this.fieldViewers) {
 | 
					 | 
				
			||||||
		ViewWidget.prototype.fieldViewers = {text: TextViewer}; // Start with the built-in text viewer
 | 
					 | 
				
			||||||
		$tw.modules.applyMethods("fieldviewer",this.fieldViewers);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Generate child nodes
 | 
					 | 
				
			||||||
	this.generate();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ViewWidget.prototype.generate = function() {
 | 
					 | 
				
			||||||
	// Get parameters from our attributes
 | 
					 | 
				
			||||||
	this.tiddlerTitle = this.renderer.getAttribute("tiddler",this.renderer.tiddlerTitle);
 | 
					 | 
				
			||||||
	this.fieldName = this.renderer.getAttribute("field","text");
 | 
					 | 
				
			||||||
	this.format = this.renderer.getAttribute("format","text");
 | 
					 | 
				
			||||||
	// Get the value to display
 | 
					 | 
				
			||||||
	var tiddler = this.renderer.renderTree.wiki.getTiddler(this.tiddlerTitle),
 | 
					 | 
				
			||||||
		value;
 | 
					 | 
				
			||||||
	if(tiddler) {
 | 
					 | 
				
			||||||
		if(this.fieldName === "text") {
 | 
					 | 
				
			||||||
			// Calling getTiddlerText() triggers lazy loading of skinny tiddlers
 | 
					 | 
				
			||||||
			value = this.renderer.renderTree.wiki.getTiddlerText(this.tiddlerTitle);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			value = tiddler.fields[this.fieldName];
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else { // Use a special value if the tiddler is missing
 | 
					 | 
				
			||||||
		switch(this.fieldName) {
 | 
					 | 
				
			||||||
			case "title":
 | 
					 | 
				
			||||||
				value = this.tiddlerTitle;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case "modified":
 | 
					 | 
				
			||||||
			case "created":
 | 
					 | 
				
			||||||
				value = new Date();
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				value = "";
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Choose the viewer to use
 | 
					 | 
				
			||||||
	var Viewer = this.fieldViewers.text;
 | 
					 | 
				
			||||||
	if($tw.utils.hop(this.fieldViewers,this.format)) {
 | 
					 | 
				
			||||||
		Viewer = this.fieldViewers[this.format];
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	this.viewer = new Viewer(this,tiddler,this.fieldName,value);
 | 
					 | 
				
			||||||
	// Ask the viewer to create the widget element
 | 
					 | 
				
			||||||
	this.viewer.render();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ViewWidget.prototype.refreshInDom = function(changedAttributes,changedTiddlers) {
 | 
					 | 
				
			||||||
	// Check if any of our attributes have changed, or if a tiddler we're interested in has changed
 | 
					 | 
				
			||||||
	if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.format || (this.tiddlerTitle && changedTiddlers[this.tiddlerTitle])) {
 | 
					 | 
				
			||||||
		// 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);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// We don't need to refresh ourselves, so just refresh any child nodes
 | 
					 | 
				
			||||||
		$tw.utils.each(this.children,function(node) {
 | 
					 | 
				
			||||||
			if(node.refreshInDom) {
 | 
					 | 
				
			||||||
				node.refreshInDom(changedTiddlers);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ViewWidget.prototype.postRenderInDom = function() {
 | 
					 | 
				
			||||||
	if(this.viewer && this.viewer.postRenderInDom) {
 | 
					 | 
				
			||||||
		this.viewer.postRenderInDom();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.view = ViewWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,41 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/view/viewers/date.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: fieldviewer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A viewer for viewing tiddler fields as a date
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var DateViewer = function(viewWidget,tiddler,field,value) {
 | 
					 | 
				
			||||||
	this.viewWidget = viewWidget;
 | 
					 | 
				
			||||||
	this.tiddler = tiddler;
 | 
					 | 
				
			||||||
	this.field = field;
 | 
					 | 
				
			||||||
	this.value = value;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
DateViewer.prototype.render = function() {
 | 
					 | 
				
			||||||
	var template = this.viewWidget.renderer.getAttribute("template","DD MMM YYYY"),
 | 
					 | 
				
			||||||
		value = "";
 | 
					 | 
				
			||||||
	if(this.value !== undefined) {
 | 
					 | 
				
			||||||
		value = $tw.utils.formatDateString(this.value,template);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Set the element details
 | 
					 | 
				
			||||||
	this.viewWidget.tag = "span";
 | 
					 | 
				
			||||||
	this.viewWidget.attributes = {
 | 
					 | 
				
			||||||
		"class": "tw-view-date"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	this.viewWidget.children = this.viewWidget.renderer.renderTree.createRenderers(this.viewWidget.renderer,[{
 | 
					 | 
				
			||||||
		type: "text",
 | 
					 | 
				
			||||||
		text: value
 | 
					 | 
				
			||||||
	}]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.date = DateViewer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,44 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/view/viewers/htmlencoded.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: fieldviewer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A viewer for viewing tiddler fields as HTML encoded text
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var HtmlEncodedViewer = function(viewWidget,tiddler,field,value) {
 | 
					 | 
				
			||||||
	this.viewWidget = viewWidget;
 | 
					 | 
				
			||||||
	this.tiddler = tiddler;
 | 
					 | 
				
			||||||
	this.field = field;
 | 
					 | 
				
			||||||
	this.value = value;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
HtmlEncodedViewer.prototype.render = function() {
 | 
					 | 
				
			||||||
	// Get the value as a string
 | 
					 | 
				
			||||||
	if(this.field !== "text" && this.tiddler) {
 | 
					 | 
				
			||||||
		this.value = this.tiddler.getFieldString(this.field);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var value = "";
 | 
					 | 
				
			||||||
	if(this.value !== undefined && this.value !== null) {
 | 
					 | 
				
			||||||
		value = this.value;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Set the element details
 | 
					 | 
				
			||||||
	this.viewWidget.tag = "span";
 | 
					 | 
				
			||||||
	this.viewWidget.attributes = {
 | 
					 | 
				
			||||||
		"class": "tw-view-htmlencoded"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	this.viewWidget.children = this.viewWidget.renderer.renderTree.createRenderers(this.viewWidget.renderer,[{
 | 
					 | 
				
			||||||
		type: "text",
 | 
					 | 
				
			||||||
		text: $tw.utils.htmlEncode(value)
 | 
					 | 
				
			||||||
	}]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.htmlencoded = HtmlEncodedViewer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,44 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/view/viewers/htmlwikified.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: fieldviewer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A viewer for viewing tiddler fields as a textual HTML representation of the wikified text
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var HtmlWikifiedViewer = function(viewWidget,tiddler,field,value) {
 | 
					 | 
				
			||||||
	this.viewWidget = viewWidget;
 | 
					 | 
				
			||||||
	this.tiddler = tiddler;
 | 
					 | 
				
			||||||
	this.field = field;
 | 
					 | 
				
			||||||
	this.value = value;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
HtmlWikifiedViewer.prototype.render = function() {
 | 
					 | 
				
			||||||
	// Parse the field text
 | 
					 | 
				
			||||||
	var wiki = this.viewWidget.renderer.renderTree.wiki,
 | 
					 | 
				
			||||||
		parser = wiki.parseText("text/vnd.tiddlywiki",this.value),
 | 
					 | 
				
			||||||
		renderTree = new $tw.WikiRenderTree(parser,{wiki: wiki, parentRenderer: this.viewWidget.renderer, document: this.viewWidget.renderer.renderTree.document});
 | 
					 | 
				
			||||||
	renderTree.execute();
 | 
					 | 
				
			||||||
	var container = this.viewWidget.renderer.renderTree.document.createElement("div");
 | 
					 | 
				
			||||||
	renderTree.renderInDom(container)
 | 
					 | 
				
			||||||
	var text = container.innerHTML;
 | 
					 | 
				
			||||||
	// Set the element details
 | 
					 | 
				
			||||||
	this.viewWidget.tag = "pre";
 | 
					 | 
				
			||||||
	this.viewWidget.attributes = {
 | 
					 | 
				
			||||||
		"class": "tw-view-htmlwikified"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	this.viewWidget.children = this.viewWidget.renderer.renderTree.createRenderers(this.viewWidget.renderer,[{
 | 
					 | 
				
			||||||
			type: "text",
 | 
					 | 
				
			||||||
			text: text
 | 
					 | 
				
			||||||
		}]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.htmlwikified = HtmlWikifiedViewer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,44 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/view/viewers/jsencoded.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: fieldviewer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A viewer for viewing tiddler fields as JavaScript stringified text
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var JsEncodedViewer = function(viewWidget,tiddler,field,value) {
 | 
					 | 
				
			||||||
	this.viewWidget = viewWidget;
 | 
					 | 
				
			||||||
	this.tiddler = tiddler;
 | 
					 | 
				
			||||||
	this.field = field;
 | 
					 | 
				
			||||||
	this.value = value;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
JsEncodedViewer.prototype.render = function() {
 | 
					 | 
				
			||||||
	// Get the value as a string
 | 
					 | 
				
			||||||
	if(this.field !== "text" && this.tiddler) {
 | 
					 | 
				
			||||||
		this.value = this.tiddler.getFieldString(this.field);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var value = "";
 | 
					 | 
				
			||||||
	if(this.value !== undefined && this.value !== null) {
 | 
					 | 
				
			||||||
		value = this.value;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Set the element details
 | 
					 | 
				
			||||||
	this.viewWidget.tag = "pre";
 | 
					 | 
				
			||||||
	this.viewWidget.attributes = {
 | 
					 | 
				
			||||||
		"class": "tw-view-jsencoded"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	this.viewWidget.children = this.viewWidget.renderer.renderTree.createRenderers(this.viewWidget.renderer,[{
 | 
					 | 
				
			||||||
			type: "text",
 | 
					 | 
				
			||||||
			text: $tw.utils.stringify(value)
 | 
					 | 
				
			||||||
		}]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.jsencoded = JsEncodedViewer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,44 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/view/viewers/link.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: fieldviewer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A viewer for viewing tiddler fields as a link
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var LinkViewer = function(viewWidget,tiddler,field,value) {
 | 
					 | 
				
			||||||
	this.viewWidget = viewWidget;
 | 
					 | 
				
			||||||
	this.tiddler = tiddler;
 | 
					 | 
				
			||||||
	this.field = field;
 | 
					 | 
				
			||||||
	this.value = value;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
LinkViewer.prototype.render = function() {
 | 
					 | 
				
			||||||
	var text = this.value === undefined ? "" : this.value;
 | 
					 | 
				
			||||||
	// Indicate that we're not generating an element
 | 
					 | 
				
			||||||
	this.viewWidget.tag = this.viewWidget.renderer.parseTreeNode.isBlock ? "div" : "span";
 | 
					 | 
				
			||||||
	this.viewWidget.attributes = {
 | 
					 | 
				
			||||||
		"class": "tw-view-link"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	this.viewWidget.children = this.viewWidget.renderer.renderTree.createRenderers(this.viewWidget.renderer,[{
 | 
					 | 
				
			||||||
			type: "element",
 | 
					 | 
				
			||||||
			tag: "$link",
 | 
					 | 
				
			||||||
			attributes: {
 | 
					 | 
				
			||||||
				to: {type: "string", value: text}
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			children: [{
 | 
					 | 
				
			||||||
				type: "text",
 | 
					 | 
				
			||||||
				text: text
 | 
					 | 
				
			||||||
			}]
 | 
					 | 
				
			||||||
		}]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.link = LinkViewer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,77 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/view/viewers/relativedate.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: fieldviewer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A viewer for viewing tiddler fields as a relative date
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var RelativeDateViewer = function(viewWidget,tiddler,field,value) {
 | 
					 | 
				
			||||||
	this.viewWidget = viewWidget;
 | 
					 | 
				
			||||||
	this.tiddler = tiddler;
 | 
					 | 
				
			||||||
	this.field = field;
 | 
					 | 
				
			||||||
	this.value = value;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RelativeDateViewer.prototype.render = function() {
 | 
					 | 
				
			||||||
	var template = this.viewWidget.renderer.getAttribute("template","DD MMM YYYY"),
 | 
					 | 
				
			||||||
		value = "";
 | 
					 | 
				
			||||||
	if(this.value !== undefined) {
 | 
					 | 
				
			||||||
		value = $tw.utils.formatDateString(this.value,template);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Set the element details
 | 
					 | 
				
			||||||
	this.viewWidget.tag = "span";
 | 
					 | 
				
			||||||
	this.viewWidget.attributes = {
 | 
					 | 
				
			||||||
		"class": "tw-view-date"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	this.viewWidget.children = this.viewWidget.renderer.renderTree.createRenderers(this.viewWidget.renderer,[{
 | 
					 | 
				
			||||||
		type: "text",
 | 
					 | 
				
			||||||
		text: value
 | 
					 | 
				
			||||||
	}]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Trigger the timer when the relative date is put into the DOM
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
RelativeDateViewer.prototype.postRenderInDom = function() {
 | 
					 | 
				
			||||||
	this.update();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Trigger the timer for the next update of the relative date
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
RelativeDateViewer.prototype.setTimer = function() {
 | 
					 | 
				
			||||||
	var self = this;
 | 
					 | 
				
			||||||
	if(this.relativeDate.updatePeriod < 24 * 60 * 60 * 1000) {
 | 
					 | 
				
			||||||
		window.setTimeout(function() {
 | 
					 | 
				
			||||||
			// Only call the update function if the dom node is still in the document
 | 
					 | 
				
			||||||
			if($tw.utils.domContains(self.viewWidget.renderer.renderTree.document,self.viewWidget.renderer.domNode)) {
 | 
					 | 
				
			||||||
				self.update.call(self);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		},this.relativeDate.updatePeriod);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Update the relative date display, and trigger the timer for the next update
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
RelativeDateViewer.prototype.update = function() {
 | 
					 | 
				
			||||||
	this.relativeDate = $tw.utils.getRelativeDate((new Date()) - this.value);
 | 
					 | 
				
			||||||
	if(this.relativeDate.delta > 0) {
 | 
					 | 
				
			||||||
		while(this.viewWidget.renderer.domNode.hasChildNodes()) {
 | 
					 | 
				
			||||||
			this.viewWidget.renderer.domNode.removeChild(this.viewWidget.renderer.domNode.firstChild);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		this.viewWidget.renderer.domNode.appendChild(this.viewWidget.renderer.renderTree.document.createTextNode(this.relativeDate.description));
 | 
					 | 
				
			||||||
		this.setTimer();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.relativedate = RelativeDateViewer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,44 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/view/viewers/urlencoded.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: fieldviewer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A viewer for viewing tiddler fields as url encoded text
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var UrlEncodedViewer = function(viewWidget,tiddler,field,value) {
 | 
					 | 
				
			||||||
	this.viewWidget = viewWidget;
 | 
					 | 
				
			||||||
	this.tiddler = tiddler;
 | 
					 | 
				
			||||||
	this.field = field;
 | 
					 | 
				
			||||||
	this.value = value;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
UrlEncodedViewer.prototype.render = function() {
 | 
					 | 
				
			||||||
	// Get the value as a string
 | 
					 | 
				
			||||||
	if(this.field !== "text" && this.tiddler) {
 | 
					 | 
				
			||||||
		this.value = this.tiddler.getFieldString(this.field);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var value = "";
 | 
					 | 
				
			||||||
	if(this.value !== undefined && this.value !== null) {
 | 
					 | 
				
			||||||
		value = this.value;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Set the element details
 | 
					 | 
				
			||||||
	this.viewWidget.tag = "span";
 | 
					 | 
				
			||||||
	this.viewWidget.attributes = {
 | 
					 | 
				
			||||||
		"class": "tw-view-urlencoded"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	this.viewWidget.children = this.viewWidget.renderer.renderTree.createRenderers(this.viewWidget.renderer,[{
 | 
					 | 
				
			||||||
		type: "text",
 | 
					 | 
				
			||||||
		text: encodeURIComponent(value)
 | 
					 | 
				
			||||||
	}]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.urlencoded = UrlEncodedViewer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -1,43 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: $:/core/modules/widgets/view/viewers/wikified.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
module-type: fieldviewer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A viewer for viewing tiddler fields as wikified text
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var WikifiedViewer = function(viewWidget,tiddler,field,value) {
 | 
					 | 
				
			||||||
	this.viewWidget = viewWidget;
 | 
					 | 
				
			||||||
	this.tiddler = tiddler;
 | 
					 | 
				
			||||||
	this.field = field;
 | 
					 | 
				
			||||||
	this.value = value;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WikifiedViewer.prototype.render = function() {
 | 
					 | 
				
			||||||
	// Set the element details
 | 
					 | 
				
			||||||
	this.viewWidget.tag = this.viewWidget.renderer.parseTreeNode.isBlock ? "div" : "span";
 | 
					 | 
				
			||||||
	this.viewWidget.attributes = {};
 | 
					 | 
				
			||||||
	var node = {
 | 
					 | 
				
			||||||
			type: "element",
 | 
					 | 
				
			||||||
			tag: "$transclude",
 | 
					 | 
				
			||||||
			attributes: {
 | 
					 | 
				
			||||||
				"class": "tw-view-wikified",
 | 
					 | 
				
			||||||
				field: {type: "string", value: this.field}
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			isBlock: this.viewWidget.renderer.parseTreeNode.isBlock
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	if(this.tiddler && this.tiddler.fields.title) {
 | 
					 | 
				
			||||||
		node.attributes.target = {type: "string", value: this.tiddler.fields.title}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	this.viewWidget.children = this.viewWidget.renderer.renderTree.createRenderers(this.viewWidget.renderer,[node]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.wikified = WikifiedViewer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -329,13 +329,13 @@ exports.getTiddlerLinks = function(title) {
 | 
				
			|||||||
	// We'll cache the links so they only get computed if the tiddler changes
 | 
						// We'll cache the links so they only get computed if the tiddler changes
 | 
				
			||||||
	return this.getCacheForTiddler(title,"links",function() {
 | 
						return this.getCacheForTiddler(title,"links",function() {
 | 
				
			||||||
		// Parse the tiddler
 | 
							// Parse the tiddler
 | 
				
			||||||
		var parser = self.parseTiddler(title);
 | 
							var parser = self.new_parseTiddler(title);
 | 
				
			||||||
		// Count up the links
 | 
							// Count up the links
 | 
				
			||||||
		var links = [],
 | 
							var links = [],
 | 
				
			||||||
			checkParseTree = function(parseTree) {
 | 
								checkParseTree = function(parseTree) {
 | 
				
			||||||
				for(var t=0; t<parseTree.length; t++) {
 | 
									for(var t=0; t<parseTree.length; t++) {
 | 
				
			||||||
					var parseTreeNode = parseTree[t];
 | 
										var parseTreeNode = parseTree[t];
 | 
				
			||||||
					if(parseTreeNode.type === "element" && parseTreeNode.tag === "$link" && parseTreeNode.attributes.to && parseTreeNode.attributes.to.type === "string") {
 | 
										if(parseTreeNode.type === "link" && parseTreeNode.attributes.to && parseTreeNode.attributes.to.type === "string") {
 | 
				
			||||||
						var value = parseTreeNode.attributes.to.value;
 | 
											var value = parseTreeNode.attributes.to.value;
 | 
				
			||||||
						if(links.indexOf(value) === -1) {
 | 
											if(links.indexOf(value) === -1) {
 | 
				
			||||||
							links.push(value);
 | 
												links.push(value);
 | 
				
			||||||
@@ -606,7 +606,7 @@ Parse a block of text of a specified MIME type
 | 
				
			|||||||
Options include:
 | 
					Options include:
 | 
				
			||||||
	parseAsInline: if true, the text of the tiddler will be parsed as an inline run
 | 
						parseAsInline: if true, the text of the tiddler will be parsed as an inline run
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
exports.parseText = function(type,text,options) {
 | 
					exports.old_parseText = function(type,text,options) {
 | 
				
			||||||
	options = options || {};
 | 
						options = options || {};
 | 
				
			||||||
	// Select a parser
 | 
						// Select a parser
 | 
				
			||||||
	var Parser = $tw.Wiki.parsers[type];
 | 
						var Parser = $tw.Wiki.parsers[type];
 | 
				
			||||||
@@ -629,13 +629,13 @@ exports.parseText = function(type,text,options) {
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
Parse a tiddler according to its MIME type
 | 
					Parse a tiddler according to its MIME type
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
exports.parseTiddler = function(title,options) {
 | 
					exports.old_parseTiddler = function(title,options) {
 | 
				
			||||||
	options = options || {};
 | 
						options = options || {};
 | 
				
			||||||
	var cacheType = options.parseAsInline ? "newInlineParseTree" : "newBlockParseTree",
 | 
						var cacheType = options.parseAsInline ? "newInlineParseTree" : "newBlockParseTree",
 | 
				
			||||||
		tiddler = this.getTiddler(title),
 | 
							tiddler = this.getTiddler(title),
 | 
				
			||||||
		self = this;
 | 
							self = this;
 | 
				
			||||||
	return tiddler ? this.getCacheForTiddler(title,cacheType,function() {
 | 
						return tiddler ? this.getCacheForTiddler(title,cacheType,function() {
 | 
				
			||||||
			return self.parseText(tiddler.fields.type,tiddler.fields.text,options);
 | 
								return self.old_parseText(tiddler.fields.type,tiddler.fields.text,options);
 | 
				
			||||||
		}) : null;
 | 
							}) : null;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -643,6 +643,7 @@ exports.parseTiddler = function(title,options) {
 | 
				
			|||||||
var tweakParseTreeNode = function(node) {
 | 
					var tweakParseTreeNode = function(node) {
 | 
				
			||||||
	if(node.type === "element" && node.tag.charAt(0) === "$") {
 | 
						if(node.type === "element" && node.tag.charAt(0) === "$") {
 | 
				
			||||||
		node.type = node.tag.substr(1);
 | 
							node.type = node.tag.substr(1);
 | 
				
			||||||
 | 
							delete node.tag;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	tweakParseTreeNodes(node.children);
 | 
						tweakParseTreeNodes(node.children);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -672,7 +673,7 @@ var tweakParser = function(parser) {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
exports.new_parseText = function(type,text,options) {
 | 
					exports.new_parseText = function(type,text,options) {
 | 
				
			||||||
	var parser = this.parseText(type,text,options);
 | 
						var parser = this.old_parseText(type,text,options);
 | 
				
			||||||
	if(parser) {
 | 
						if(parser) {
 | 
				
			||||||
		tweakParser(parser)
 | 
							tweakParser(parser)
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
@@ -680,7 +681,7 @@ exports.new_parseText = function(type,text,options) {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
exports.new_parseTiddler = function(title,options) {
 | 
					exports.new_parseTiddler = function(title,options) {
 | 
				
			||||||
	var parser = this.parseTiddler(title,options);
 | 
						var parser = this.old_parseTiddler(title,options);
 | 
				
			||||||
	if(parser) {
 | 
						if(parser) {
 | 
				
			||||||
		tweakParser(parser)
 | 
							tweakParser(parser)
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
@@ -706,21 +707,6 @@ exports.new_parseTextReference = function(title,field,index,options) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Parse text in a specified format and render it into another format
 | 
					 | 
				
			||||||
	outputType: content type for the output
 | 
					 | 
				
			||||||
	textType: content type of the input text
 | 
					 | 
				
			||||||
	text: input text
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
exports.renderText = function(outputType,textType,text,context) {
 | 
					 | 
				
			||||||
	var parser = this.parseText(textType,text),
 | 
					 | 
				
			||||||
		renderTree = new $tw.WikiRenderTree(parser,{wiki: this, context: context, document: $tw.document});
 | 
					 | 
				
			||||||
	renderTree.execute();
 | 
					 | 
				
			||||||
	var container = $tw.document.createElement("div");
 | 
					 | 
				
			||||||
	renderTree.renderInDom(container)
 | 
					 | 
				
			||||||
	return outputType === "text/html" ? container.innerHTML : container.textContent;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
Parse text in a specified format and render it into another format
 | 
					Parse text in a specified format and render it into another format
 | 
				
			||||||
	outputType: content type for the output
 | 
						outputType: content type for the output
 | 
				
			||||||
@@ -740,27 +726,13 @@ exports.new_renderText = function(outputType,textType,text,parentWidget) {
 | 
				
			|||||||
	return outputType === "text/html" ? container.innerHTML : container.textContent;
 | 
						return outputType === "text/html" ? container.innerHTML : container.textContent;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Parse text from a tiddler and render it into another format
 | 
					 | 
				
			||||||
	outputType: content type for the output
 | 
					 | 
				
			||||||
	title: title of the tiddler to be rendered
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
exports.renderTiddler = function(outputType,title,context) {
 | 
					 | 
				
			||||||
	var parser = this.parseTiddler(title),
 | 
					 | 
				
			||||||
		renderTree = new $tw.WikiRenderTree(parser,{wiki: this, context: context, document: $tw.document});
 | 
					 | 
				
			||||||
	renderTree.execute();
 | 
					 | 
				
			||||||
	var container = $tw.document.createElement("div");
 | 
					 | 
				
			||||||
	renderTree.renderInDom(container)
 | 
					 | 
				
			||||||
	return outputType === "text/html" ? container.innerHTML : container.textContent;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
Parse text from a tiddler and render it into another format
 | 
					Parse text from a tiddler and render it into another format
 | 
				
			||||||
	outputType: content type for the output
 | 
						outputType: content type for the output
 | 
				
			||||||
	title: title of the tiddler to be rendered
 | 
						title: title of the tiddler to be rendered
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
exports.new_renderTiddler = function(outputType,title,parentWidget) {
 | 
					exports.new_renderTiddler = function(outputType,title,parentWidget) {
 | 
				
			||||||
	var parser = $tw.wiki.new_parseTiddler(title),
 | 
						var parser = this.new_parseTiddler(title),
 | 
				
			||||||
		parseTreeNode = parser ? {type: "widget", children: parser.tree} : undefined,
 | 
							parseTreeNode = parser ? {type: "widget", children: parser.tree} : undefined,
 | 
				
			||||||
		widgetNode = new widget.widget(parseTreeNode,{
 | 
							widgetNode = new widget.widget(parseTreeNode,{
 | 
				
			||||||
			wiki: this,
 | 
								wiki: this,
 | 
				
			||||||
@@ -821,7 +793,7 @@ exports.saveWiki = function(options) {
 | 
				
			|||||||
	options = options || {};
 | 
						options = options || {};
 | 
				
			||||||
	var template = options.template || "$:/core/templates/tiddlywiki5.template.html",
 | 
						var template = options.template || "$:/core/templates/tiddlywiki5.template.html",
 | 
				
			||||||
		downloadType = options.downloadType || "text/plain";
 | 
							downloadType = options.downloadType || "text/plain";
 | 
				
			||||||
	var text = this.renderTiddler(downloadType,template);
 | 
						var text = this.new_renderTiddler(downloadType,template);
 | 
				
			||||||
	this.callSaver("save",text,function(err) {
 | 
						this.callSaver("save",text,function(err) {
 | 
				
			||||||
		$tw.notifier.display("$:/messages/Saved");
 | 
							$tw.notifier.display("$:/messages/Saved");
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,47 +0,0 @@
 | 
				
			|||||||
/*\
 | 
					 | 
				
			||||||
title: test-wikitext.js
 | 
					 | 
				
			||||||
type: application/javascript
 | 
					 | 
				
			||||||
tags: [[$:/tags/test-spec]]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Tests the wikitext rendering pipeline end-to-end. We also need tests that individually test parsers, rendertreenodes etc., but this gets us started.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
\*/
 | 
					 | 
				
			||||||
(function(){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*jslint node: true, browser: true */
 | 
					 | 
				
			||||||
/*global $tw: false */
 | 
					 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
describe("WikiText tests", function() {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Create a wiki
 | 
					 | 
				
			||||||
	var wiki = new $tw.Wiki();
 | 
					 | 
				
			||||||
	// Add a couple of tiddlers
 | 
					 | 
				
			||||||
	wiki.addTiddler({title: "TiddlerOne", text: "The quick brown fox"});
 | 
					 | 
				
			||||||
	wiki.addTiddler({title: "TiddlerTwo", text: "The rain in Spain\nfalls mainly on the plain"});
 | 
					 | 
				
			||||||
	wiki.addTiddler({title: "TiddlerThree", text: "The speed of sound\n\nThe light of speed"});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	it("should render tiddlers with no special markup render as-is", function() {
 | 
					 | 
				
			||||||
		expect(wiki.renderTiddler("text/plain","TiddlerOne")).toBe("The quick brown fox");
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	it("should preserve single new lines", function() {
 | 
					 | 
				
			||||||
		expect(wiki.renderTiddler("text/plain","TiddlerTwo")).toBe("The rain in Spain\nfalls mainly on the plain");
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	it("should use double new lines to create paragraphs", function() {
 | 
					 | 
				
			||||||
		// The paragraphs are lost in the conversion to plain text
 | 
					 | 
				
			||||||
		expect(wiki.renderTiddler("text/plain","TiddlerThree")).toBe("The speed of soundThe light of speed");
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	it("should render plain text tiddlers as a paragraph", function() {
 | 
					 | 
				
			||||||
		expect(wiki.renderTiddler("text/html","TiddlerOne")).toBe("<p>\nThe quick brown fox</p>");
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	it("should preserve single new lines", function() {
 | 
					 | 
				
			||||||
		expect(wiki.renderTiddler("text/html","TiddlerTwo")).toBe("<p>\nThe rain in Spain\nfalls mainly on the plain</p>");
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	it("should use double new lines to create paragraphs", function() {
 | 
					 | 
				
			||||||
		expect(wiki.renderTiddler("text/html","TiddlerThree")).toBe("<p>\nThe speed of sound</p><p>\nThe light of speed</p>");
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@@ -19,7 +19,7 @@ describe("WikiText parser tests", function() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Define a parsing shortcut
 | 
						// Define a parsing shortcut
 | 
				
			||||||
	var parse = function(text) {
 | 
						var parse = function(text) {
 | 
				
			||||||
		return wiki.parseText("text/vnd.tiddlywiki",text).tree;
 | 
							return wiki.new_parseText("text/vnd.tiddlywiki",text).tree;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	it("should parse tags", function() {
 | 
						it("should parse tags", function() {
 | 
				
			||||||
@@ -70,7 +70,7 @@ describe("WikiText parser tests", function() {
 | 
				
			|||||||
		);
 | 
							);
 | 
				
			||||||
		expect(parse("<$reveal state='$:/temp/search' type='nomatch' text=''>")).toEqual(
 | 
							expect(parse("<$reveal state='$:/temp/search' type='nomatch' text=''>")).toEqual(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			[ { type : 'element', tag : 'p', children : [ { type : 'element', start : 0, attributes : { state : { start : 8, name : 'state', type : 'string', value : '$:/temp/search', end : 31 }, type : { start : 31, name : 'type', type : 'string', value : 'nomatch', end : 46 }, text : { start : 46, name : 'text', type : 'string', value : '', end : 54 } }, tag : '$reveal', end : 55, children : [  ], isBlock : false } ] } ]
 | 
								[ { type : 'element', tag : 'p', children : [ { type : 'reveal', start : 0, attributes : { state : { start : 8, name : 'state', type : 'string', value : '$:/temp/search', end : 31 }, type : { start : 31, name : 'type', type : 'string', value : 'nomatch', end : 46 }, text : { start : 46, name : 'text', type : 'string', value : '', end : 54 } }, end : 55, isBlock : false, children : [  ] } ] } ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		);
 | 
							);
 | 
				
			||||||
		expect(parse("<div attribute={{TiddlerTitle!!field}}>some text</div>")).toEqual(
 | 
							expect(parse("<div attribute={{TiddlerTitle!!field}}>some text</div>")).toEqual(
 | 
				
			||||||
@@ -93,7 +93,7 @@ describe("WikiText parser tests", function() {
 | 
				
			|||||||
	it("should parse macro definitions", function() {
 | 
						it("should parse macro definitions", function() {
 | 
				
			||||||
		expect(parse("\\define myMacro()\nnothing\n\\end\n")).toEqual(
 | 
							expect(parse("\\define myMacro()\nnothing\n\\end\n")).toEqual(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			[ { type : 'macrodef', name : 'myMacro', params : [  ], text : 'nothing' } ]
 | 
								[ { type : 'setvariable', name : 'myMacro', params : [  ], text : 'nothing', attributes : { name : { type : 'string', value : 'myMacro' }, value : { type : 'string', value : 'nothing' } }, children : [  ] } ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		);
 | 
							);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,30 +23,29 @@ describe("WikiText tests", function() {
 | 
				
			|||||||
	wiki.addTiddler({title: "TiddlerFour", text: "\\define my-macro(adjective:'groovy')\nThis is my ''amazingly'' $adjective$ macro!\n\\end\n\n<$link to=<<my-macro>>>This is a link</$link>"});
 | 
						wiki.addTiddler({title: "TiddlerFour", text: "\\define my-macro(adjective:'groovy')\nThis is my ''amazingly'' $adjective$ macro!\n\\end\n\n<$link to=<<my-macro>>>This is a link</$link>"});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	it("should render tiddlers with no special markup as-is", function() {
 | 
						it("should render tiddlers with no special markup as-is", function() {
 | 
				
			||||||
		expect(wiki.renderTiddler("text/plain","TiddlerOne")).toBe("The quick brown fox");
 | 
							expect(wiki.new_renderTiddler("text/plain","TiddlerOne")).toBe("The quick brown fox");
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
	it("should preserve single new lines", function() {
 | 
						it("should preserve single new lines", function() {
 | 
				
			||||||
		expect(wiki.renderTiddler("text/plain","TiddlerTwo")).toBe("The rain in Spain\nfalls mainly on the plain");
 | 
							expect(wiki.new_renderTiddler("text/plain","TiddlerTwo")).toBe("The rain in Spain\nfalls mainly on the plain");
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
	it("should use double new lines to create paragraphs", function() {
 | 
						it("should use double new lines to create paragraphs", function() {
 | 
				
			||||||
		// The paragraphs are lost in the conversion to plain text
 | 
							// The paragraphs are lost in the conversion to plain text
 | 
				
			||||||
		expect(wiki.renderTiddler("text/plain","TiddlerThree")).toBe("The speed of soundThe light of speed");
 | 
							expect(wiki.new_renderTiddler("text/plain","TiddlerThree")).toBe("The speed of soundThe light of speed");
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	it("should render plain text tiddlers as a paragraph", function() {
 | 
						it("should render plain text tiddlers as a paragraph", function() {
 | 
				
			||||||
		expect(wiki.renderTiddler("text/html","TiddlerOne")).toBe("<p>\nThe quick brown fox</p>");
 | 
							expect(wiki.new_renderTiddler("text/html","TiddlerOne")).toBe("<p>\nThe quick brown fox</p>");
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
	it("should preserve single new lines", function() {
 | 
						it("should preserve single new lines", function() {
 | 
				
			||||||
		expect(wiki.renderTiddler("text/html","TiddlerTwo")).toBe("<p>\nThe rain in Spain\nfalls mainly on the plain</p>");
 | 
							expect(wiki.new_renderTiddler("text/html","TiddlerTwo")).toBe("<p>\nThe rain in Spain\nfalls mainly on the plain</p>");
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
	it("should use double new lines to create paragraphs", function() {
 | 
						it("should use double new lines to create paragraphs", function() {
 | 
				
			||||||
		expect(wiki.renderTiddler("text/html","TiddlerThree")).toBe("<p>\nThe speed of sound</p><p>\nThe light of speed</p>");
 | 
							expect(wiki.new_renderTiddler("text/html","TiddlerThree")).toBe("<p>\nThe speed of sound</p><p>\nThe light of speed</p>");
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
	it("should support attributes specified as macro invocations", function() {
 | 
						it("should support attributes specified as macro invocations", function() {
 | 
				
			||||||
		expect(wiki.renderTiddler("text/html","TiddlerFour")).toBe("<p>\n<a class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing' href='#This%20is%20my%20amazingly%20groovy%20macro!'>\nThis is a link</a></p>");
 | 
							expect(wiki.new_renderTiddler("text/html","TiddlerFour")).toBe("<p>\n<a class=' tw-tiddlylink tw-tiddlylink-missing' href='#This%20is%20my%20amazingly%20groovy%20macro!'>\nThis is a link</a></p>");
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
})();
 | 
					})();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,7 @@
 | 
				
			|||||||
<h1 class=''>
 | 
					<h1 class=''>
 | 
				
			||||||
Building classic <span>
 | 
					Building classic <span>
 | 
				
			||||||
TiddlyWiki</span> with <span>
 | 
					TiddlyWiki</span> with <span>
 | 
				
			||||||
TiddlyWiki5</span></h1><div class='tw-tiddler'>
 | 
					TiddlyWiki5</span></h1><p>
 | 
				
			||||||
<div class='tw-transclude'>
 | 
					 | 
				
			||||||
<p>
 | 
					 | 
				
			||||||
<span>
 | 
					<span>
 | 
				
			||||||
TiddlyWiki5</span> can be used to build older 2.x.x versions of <span>
 | 
					TiddlyWiki5</span> can be used to build older 2.x.x versions of <span>
 | 
				
			||||||
TiddlyWiki</span> from their constituent components. Doing so involves these additional features over and above those used for building <span>
 | 
					TiddlyWiki</span> from their constituent components. Doing so involves these additional features over and above those used for building <span>
 | 
				
			||||||
@@ -34,4 +32,4 @@ node ../../tiddlywiki.js \
 | 
				
			|||||||
	--verbose \
 | 
						--verbose \
 | 
				
			||||||
	--load <path_to_recipe_file> \
 | 
						--load <path_to_recipe_file> \
 | 
				
			||||||
	--rendertiddler $:/core/templates/tiddlywiki2.template.html <path_to_write_index_file> text/plain \
 | 
						--rendertiddler $:/core/templates/tiddlywiki2.template.html <path_to_write_index_file> text/plain \
 | 
				
			||||||
	|| exit 1</pre></div></div>
 | 
						|| exit 1</pre>
 | 
				
			||||||
							
								
								
									
										4
									
								
								ginsu.sh
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								ginsu.sh
									
									
									
									
									
								
							@@ -9,6 +9,6 @@ node ./tiddlywiki.js \
 | 
				
			|||||||
	./editions/empty \
 | 
						./editions/empty \
 | 
				
			||||||
	--verbose \
 | 
						--verbose \
 | 
				
			||||||
	--load $1 \
 | 
						--load $1 \
 | 
				
			||||||
	--rendertiddler $:/core/templates/split-recipe tmp/ginsu/split.recipe text/plain \
 | 
						--new_rendertiddler $:/core/templates/split-recipe tmp/ginsu/split.recipe text/plain \
 | 
				
			||||||
	--rendertiddlers [!is[system]] $:/core/templates/tid-tiddler tmp/ginsu text/plain .tid \
 | 
						--new_rendertiddlers [!is[system]] $:/core/templates/tid-tiddler tmp/ginsu text/plain .tid \
 | 
				
			||||||
	|| exit 1
 | 
						|| exit 1
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								test.sh
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								test.sh
									
									
									
									
									
								
							@@ -20,6 +20,6 @@ echo "Using TW5_BUILD_OUTPUT as [$TW5_BUILD_OUTPUT]"
 | 
				
			|||||||
node ./tiddlywiki.js \
 | 
					node ./tiddlywiki.js \
 | 
				
			||||||
	./editions/test \
 | 
						./editions/test \
 | 
				
			||||||
	--verbose \
 | 
						--verbose \
 | 
				
			||||||
	--rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/test.html text/plain \
 | 
						--new_rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/test.html text/plain \
 | 
				
			||||||
	|| exit 1
 | 
						|| exit 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								wbld.sh
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								wbld.sh
									
									
									
									
									
								
							@@ -15,7 +15,7 @@ mkdir -p tmp
 | 
				
			|||||||
node ./tiddlywiki.js \
 | 
					node ./tiddlywiki.js \
 | 
				
			||||||
	editions/tw5tiddlyweb \
 | 
						editions/tw5tiddlyweb \
 | 
				
			||||||
	--verbose \
 | 
						--verbose \
 | 
				
			||||||
	--rendertiddler $:/core/templates/tiddlywiki5.template.html tmp/tiddlyweb.html text/plain \
 | 
						--new_rendertiddler $:/core/templates/tiddlywiki5.template.html tmp/tiddlyweb.html text/plain \
 | 
				
			||||||
	|| exit 1
 | 
						|| exit 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Prepend the type information that TiddlyWeb needs to turn the .html file into a .tid file
 | 
					# Prepend the type information that TiddlyWeb needs to turn the .html file into a .tid file
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user