mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-09-17 07:11:22 +00:00
Fix popup position if popup is triggered from within an offsetParent element (#6887)
* Fix popup location for tables This commit introduces the `popupAbsCoords` option to the $button widget and implements an absolut coordinate format. Coordinates for popups are stored in the format `(x,y,w,h)`. These coordinates are relative to the offset parent of the element that defines the popup. This commits adds a second format `@(x,y,w,h)`. Coordinates specified in this format a relative to the pages root element. The `popupAbsCoords` option of the $button widget enables the use of this coordinates. * Unify the declaration of the RegEx for parsing the popup-position The regular expression was declared in three locations with the same content. This commit supplies a new function `parseCoordinates` in `popup.js`. This function returns the parsed coordinates and understands the classic/absolute coordinates. This function is used in `reveal.js` and `action-popup.js` to parse the coordinates. * Add documentation for coordinate systems * Consolidate creating coordinate strings The Popup object now contains a `buildCoordinates` method that can be used to build coordinate strings. It takes an "enum" for the coordinate- system to use. This makes everything easily extensible and prevents the use of magic values. * Add tests for `parseCoordinates` and `buildCoordinates` * Add `tv-popup-abs-coords` to `collectDOMVariables` This will make the absolute coordinates available for the `DraggableWidget` and the `EventCatcherWidget`. * Add documentation for the `tv-popup-abs-coords` ... to the `DraggableWidget` and the `EventCatcherWidget`.
This commit is contained in:
@@ -57,20 +57,20 @@ Invoke the action associated with this widget
|
||||
*/
|
||||
ActionPopupWidget.prototype.invokeAction = function(triggeringWidget,event) {
|
||||
// Trigger the popup
|
||||
var popupLocationRegExp = /^\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/,
|
||||
match = popupLocationRegExp.exec(this.actionCoords || "");
|
||||
if(match) {
|
||||
var coordinates = $tw.popup.parseCoordinates(this.actionCoords || "");
|
||||
if(coordinates) {
|
||||
$tw.popup.triggerPopup({
|
||||
domNode: null,
|
||||
domNodeRect: {
|
||||
left: parseFloat(match[1]),
|
||||
top: parseFloat(match[2]),
|
||||
width: parseFloat(match[3]),
|
||||
height: parseFloat(match[4])
|
||||
left: coordinates.left,
|
||||
top: coordinates.top,
|
||||
width: coordinates.width,
|
||||
height: coordinates.height
|
||||
},
|
||||
title: this.actionState,
|
||||
wiki: this.wiki,
|
||||
floating: this.floating
|
||||
floating: this.floating,
|
||||
absolute: coordinates.absolute
|
||||
});
|
||||
} else {
|
||||
$tw.popup.cancel(0);
|
||||
|
||||
@@ -173,6 +173,7 @@ ButtonWidget.prototype.triggerPopup = function(event) {
|
||||
if(this.popupTitle) {
|
||||
$tw.popup.triggerPopup({
|
||||
domNode: this.domNodes[0],
|
||||
absolute: (this.popupAbsCoords === "yes"),
|
||||
title: this.popupTitle,
|
||||
wiki: this.wiki,
|
||||
noStateReference: true
|
||||
@@ -180,6 +181,7 @@ ButtonWidget.prototype.triggerPopup = function(event) {
|
||||
} else {
|
||||
$tw.popup.triggerPopup({
|
||||
domNode: this.domNodes[0],
|
||||
absolute: (this.popupAbsCoords === "yes"),
|
||||
title: this.popup,
|
||||
wiki: this.wiki
|
||||
});
|
||||
@@ -223,6 +225,7 @@ ButtonWidget.prototype.execute = function() {
|
||||
this.setField = this.getAttribute("setField");
|
||||
this.setIndex = this.getAttribute("setIndex");
|
||||
this.popupTitle = this.getAttribute("popupTitle");
|
||||
this.popupAbsCoords = this.getAttribute("popupAbsCoords", "no");
|
||||
this.tabIndex = this.getAttribute("tabindex");
|
||||
this.isDisabled = this.getAttribute("disabled","no");
|
||||
// Make child widgets
|
||||
@@ -252,7 +255,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
|
||||
*/
|
||||
ButtonWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled || changedAttributes["default"]) {
|
||||
if(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.popupAbsCoords || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled || changedAttributes["default"]) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else if(changedAttributes["class"]) {
|
||||
|
||||
@@ -94,6 +94,13 @@ RevealWidget.prototype.positionPopup = function(domNode) {
|
||||
left = Math.max(0,left);
|
||||
top = Math.max(0,top);
|
||||
}
|
||||
if (this.popup.absolute) {
|
||||
// Traverse the offsetParent chain and correct the offset to make it relative to the parent node.
|
||||
for (var offsetParentDomNode = domNode.offsetParent; offsetParentDomNode; offsetParentDomNode = offsetParentDomNode.offsetParent) {
|
||||
left -= offsetParentDomNode.offsetLeft;
|
||||
top -= offsetParentDomNode.offsetTop;
|
||||
}
|
||||
}
|
||||
domNode.style.left = left + "px";
|
||||
domNode.style.top = top + "px";
|
||||
};
|
||||
@@ -183,19 +190,11 @@ RevealWidget.prototype.compareStateText = function(state) {
|
||||
};
|
||||
|
||||
RevealWidget.prototype.readPopupState = function(state) {
|
||||
var popupLocationRegExp = /^\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/,
|
||||
match = popupLocationRegExp.exec(state);
|
||||
this.popup = $tw.popup.parseCoordinates(state);
|
||||
// Check if the state matches the location regexp
|
||||
if(match) {
|
||||
if(this.popup) {
|
||||
// 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;
|
||||
|
||||
Reference in New Issue
Block a user