mirror of
https://github.com/Jermolene/TiddlyWiki5.git
synced 2026-01-03 07:42:37 -08:00
* Jeremy's original version of the event widget * Renamed to eventcatcher, added modifier key support and mouse button support as variables * Allow updating classname without re-rendering entire widget * Handle tag attribute in refresh handler * Improve handling for mouse button variable * Fix typo in refresh handler * Added variables for position of selected node and position of event relative to selected node and catcher node
146 lines
No EOL
4.6 KiB
JavaScript
146 lines
No EOL
4.6 KiB
JavaScript
/*\
|
|
title: $:/core/modules/widgets/eventcatcher.js
|
|
type: application/javascript
|
|
module-type: widget
|
|
|
|
Event handler widget
|
|
|
|
\*/
|
|
(function(){
|
|
|
|
/*jslint node: true, browser: true */
|
|
/*global $tw: false */
|
|
"use strict";
|
|
|
|
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
|
|
|
var EventWidget = function(parseTreeNode,options) {
|
|
this.initialise(parseTreeNode,options);
|
|
};
|
|
|
|
/*
|
|
Inherit from the base widget class
|
|
*/
|
|
EventWidget.prototype = new Widget();
|
|
|
|
/*
|
|
Render this widget into the DOM
|
|
*/
|
|
EventWidget.prototype.render = function(parent,nextSibling) {
|
|
var self = this;
|
|
// Remember parent
|
|
this.parentDomNode = parent;
|
|
// Compute attributes and execute state
|
|
this.computeAttributes();
|
|
this.execute();
|
|
// Create element
|
|
var tag = this.parseTreeNode.isBlock ? "div" : "span";
|
|
if(this.elementTag && $tw.config.htmlUnsafeElements.indexOf(this.elementTag) === -1) {
|
|
tag = this.elementTag;
|
|
}
|
|
var domNode = this.document.createElement(tag);
|
|
this.domNode = domNode;
|
|
// Assign classes
|
|
this.assignDomNodeClasses();
|
|
// Add our event handler
|
|
domNode.addEventListener(this.type,function(event) {
|
|
var selector = self.getAttribute("selector"),
|
|
actions = self.getAttribute("actions"),
|
|
selectedNode = event.target,
|
|
selectedNodeRect,
|
|
catcherNodeRect,
|
|
variables = {};
|
|
if(selector) {
|
|
// Search ancestors for a node that matches the selector
|
|
while(!selectedNode.matches(selector) && selectedNode !== domNode) {
|
|
selectedNode = selectedNode.parentNode;
|
|
}
|
|
// If we found one, copy the attributes as variables, otherwise exit
|
|
if(selectedNode.matches(selector)) {
|
|
$tw.utils.each(selectedNode.attributes,function(attribute) {
|
|
variables["dom-" + attribute.name] = attribute.value;
|
|
});
|
|
//Add a variable with a popup coordinate string for the selected node
|
|
variables["tv-popup-coords"] = "(" + selectedNode.offsetLeft + "," + selectedNode.offsetTop +"," + selectedNode.offsetWidth + "," + selectedNode.offsetHeight + ")";
|
|
|
|
//Add variables for offset of selected node
|
|
variables["tv-selectednode-posx"] = selectedNode.offsetLeft;
|
|
variables["tv-selectednode-posy"] = selectedNode.offsetTop;
|
|
variables["tv-selectednode-width"] = selectedNode.offsetWidth;
|
|
variables["tv-selectednode-height"] = selectedNode.offsetHeight;
|
|
|
|
//Add variables for event X and Y position relative to selected node
|
|
selectedNodeRect = selectedNode.getBoundingClientRect();
|
|
variables["event-fromselected-posx"] = event.clientX - selectedNodeRect.left;
|
|
variables["event-fromselected-posy"] = event.clientY - selectedNodeRect.top;
|
|
|
|
//Add variables for event X and Y position relative to event catcher node
|
|
catcherNodeRect = self.domNode.getBoundingClientRect();
|
|
variables["event-fromcatcher-posx"] = event.clientX - catcherNodeRect.left;
|
|
variables["event-fromcatcher-posy"] = event.clientY - catcherNodeRect.top;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
// Execute our actions with the variables
|
|
if(actions) {
|
|
// Add a variable for the modifier key
|
|
variables.modifier = $tw.keyboardManager.getEventModifierKeyDescriptor(event);
|
|
// Add a variable for the mouse button
|
|
if("button" in event) {
|
|
if(event.button === 0) {
|
|
variables["event-mousebutton"] = "left";
|
|
} else if(event.button === 1) {
|
|
variables["event-mousebutton"] = "middle";
|
|
} else if(event.button === 2) {
|
|
variables["event-mousebutton"] = "right";
|
|
}
|
|
}
|
|
self.invokeActionString(actions,self,event,variables);
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
return true;
|
|
}
|
|
return false;
|
|
},false);
|
|
// Insert element
|
|
parent.insertBefore(domNode,nextSibling);
|
|
this.renderChildren(domNode,null);
|
|
this.domNodes.push(domNode);
|
|
};
|
|
|
|
/*
|
|
Compute the internal state of the widget
|
|
*/
|
|
EventWidget.prototype.execute = function() {
|
|
var self = this;
|
|
// Get attributes that require a refresh on change
|
|
this.type = this.getAttribute("type");
|
|
this.elementTag = this.getAttribute("tag");
|
|
// Make child widgets
|
|
this.makeChildWidgets();
|
|
};
|
|
|
|
EventWidget.prototype.assignDomNodeClasses = function() {
|
|
var classes = this.getAttribute("class","").split(" ");
|
|
classes.push("tc-eventcatcher");
|
|
this.domNode.className = classes.join(" ");
|
|
};
|
|
|
|
/*
|
|
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
|
*/
|
|
EventWidget.prototype.refresh = function(changedTiddlers) {
|
|
var changedAttributes = this.computeAttributes();
|
|
if(changedAttributes.type || changedAttributes["tag"]) {
|
|
this.refreshSelf();
|
|
return true;
|
|
} else if(changedAttributes["class"]) {
|
|
this.assignDomNodeClasses();
|
|
}
|
|
return this.refreshChildren(changedTiddlers);
|
|
};
|
|
|
|
exports.eventcatcher = EventWidget;
|
|
|
|
})(); |