mirror of
https://github.com/TiddlyWiki/TiddlyWiki5.git
synced 2026-02-01 23:47:35 +00:00
Adds info tiddlers for viewport dimensions (#9260)
* feat: added info tiddlers for viewport dimensions * feat: multi window support for dimensions info tiddlers * refactor: introduce standalone eventbus and refactor for ES2017 * docs: extended docs for InfoMechanism to cover new additions
This commit is contained in:
86
core/modules/info/dimensions.js
Normal file
86
core/modules/info/dimensions.js
Normal file
@@ -0,0 +1,86 @@
|
||||
/*\
|
||||
title: $:/core/modules/info/windowdimensions.js
|
||||
type: application/javascript
|
||||
module-type: info
|
||||
\*/
|
||||
|
||||
exports.getInfoTiddlerFields = function(updateInfoTiddlersCallback) {
|
||||
if(!$tw.browser) {
|
||||
return [];
|
||||
}
|
||||
|
||||
class WindowDimensionsTracker {
|
||||
constructor(updateCallback) {
|
||||
this.updateCallback = updateCallback;
|
||||
this.resizeHandlers = new Map();
|
||||
this.dimensionsInfo = [
|
||||
["outer/width", win => win.outerWidth],
|
||||
["outer/height", win => win.outerHeight],
|
||||
["inner/width", win => win.innerWidth],
|
||||
["inner/height", win => win.innerHeight],
|
||||
["client/width", win => win.document.documentElement.clientWidth],
|
||||
["client/height", win => win.document.documentElement.clientHeight]
|
||||
];
|
||||
}
|
||||
|
||||
buildTiddlers(win,windowId) {
|
||||
const prefix = `$:/info/browser/window/${windowId}/`;
|
||||
return this.dimensionsInfo.map(([suffix, getter]) => ({
|
||||
title: prefix + suffix,
|
||||
text: String(getter(win))
|
||||
}));
|
||||
}
|
||||
|
||||
clearTiddlers(windowId) {
|
||||
const prefix = `$:/info/browser/window/${windowId}/`,
|
||||
deletions = this.dimensionsInfo.map(([suffix]) => prefix + suffix);
|
||||
this.updateCallback([], deletions);
|
||||
}
|
||||
|
||||
getUpdateHandler(win,windowId) {
|
||||
let scheduled = false;
|
||||
return () => {
|
||||
if(!scheduled) {
|
||||
scheduled = true;
|
||||
requestAnimationFrame(() => {
|
||||
this.updateCallback(this.buildTiddlers(win,windowId), []);
|
||||
scheduled = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
trackWindow(win,windowId) {
|
||||
const handler = this.getUpdateHandler(win, windowId);
|
||||
handler(); // initial update
|
||||
win.addEventListener("resize",handler,{passive:true});
|
||||
this.resizeHandlers.set(windowId,{win, handler});
|
||||
}
|
||||
|
||||
untrackWindow(windowId) {
|
||||
const entry = this.resizeHandlers.get(windowId);
|
||||
if(entry) {
|
||||
entry.win.removeEventListener("resize", entry.handler);
|
||||
this.resizeHandlers.delete(windowId);
|
||||
}
|
||||
this.clearTiddlers(windowId);
|
||||
}
|
||||
}
|
||||
|
||||
const tracker = new WindowDimensionsTracker(updateInfoTiddlersCallback);
|
||||
|
||||
// Track main window
|
||||
tracker.trackWindow(window,"system/main");
|
||||
|
||||
// Hook into event bus for user windows
|
||||
if($tw.eventBus) {
|
||||
$tw.eventBus.on("window:opened", ({window: win, windowID}) => {
|
||||
tracker.trackWindow(win, "user/" + windowID);
|
||||
});
|
||||
$tw.eventBus.on("window:closed", ({windowID}) => {
|
||||
tracker.untrackWindow("user/" + windowID);
|
||||
});
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
46
core/modules/startup/eventbus.js
Normal file
46
core/modules/startup/eventbus.js
Normal file
@@ -0,0 +1,46 @@
|
||||
/*\
|
||||
title: $:/core/modules/startup/eventbus.js
|
||||
type: application/javascript
|
||||
module-type: startup
|
||||
|
||||
Event bus for cross module communication
|
||||
\*/
|
||||
|
||||
exports.name = "eventbus";
|
||||
exports.platforms = ["browser"];
|
||||
exports.before = ["windows"];
|
||||
exports.synchronous = true;
|
||||
|
||||
$tw.eventBus = {
|
||||
listenersMap: new Map(),
|
||||
|
||||
on(event,handler) {
|
||||
if(!this.listenersMap.has(event)) {
|
||||
this.listenersMap.set(event,new Set());
|
||||
}
|
||||
const listeners = this.listenersMap.get(event);
|
||||
listeners.add(handler);
|
||||
},
|
||||
|
||||
off(event,handler) {
|
||||
const listeners = this.listenersMap.get(event);
|
||||
if(listeners) {
|
||||
listeners.delete(handler);
|
||||
}
|
||||
},
|
||||
|
||||
once(event,handler) {
|
||||
const wrapper = (...args) => {
|
||||
handler(...args);
|
||||
this.off(event, wrapper);
|
||||
};
|
||||
this.on(event, wrapper);
|
||||
},
|
||||
|
||||
emit(event,data) {
|
||||
const listeners = this.listenersMap.get(event);
|
||||
if(listeners) {
|
||||
listeners.forEach(fn => fn(data));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -19,11 +19,17 @@ var TITLE_INFO_PLUGIN = "$:/temp/info-plugin";
|
||||
|
||||
exports.startup = function() {
|
||||
// Function to bake the info plugin with new tiddlers
|
||||
var updateInfoPlugin = function(tiddlerFieldsArray) {
|
||||
// additions: array of tiddler field objects
|
||||
// removals: array of titles to remove
|
||||
var updateInfoPlugin = function(additions = [], removals = []) {
|
||||
// Get the existing tiddlers
|
||||
var json = $tw.wiki.getTiddlerData(TITLE_INFO_PLUGIN,{tiddlers: {}});
|
||||
// Add the new ones
|
||||
$tw.utils.each(tiddlerFieldsArray,function(fields) {
|
||||
$tw.utils.each(removals,function(title) {
|
||||
if(json.tiddlers[title]) {
|
||||
delete json.tiddlers[title];
|
||||
}
|
||||
});
|
||||
$tw.utils.each(additions,function(fields) {
|
||||
if(fields && fields.title) {
|
||||
json.tiddlers[fields.title] = fields;
|
||||
}
|
||||
@@ -47,7 +53,7 @@ exports.startup = function() {
|
||||
}
|
||||
});
|
||||
updateInfoPlugin(tiddlerFieldsArray);
|
||||
var changes = $tw.wiki.readPluginInfo([TITLE_INFO_PLUGIN]);
|
||||
$tw.wiki.readPluginInfo([TITLE_INFO_PLUGIN]);
|
||||
$tw.wiki.registerPluginTiddlers("info",[TITLE_INFO_PLUGIN]);
|
||||
$tw.wiki.unpackPluginTiddlers();
|
||||
};
|
||||
|
||||
@@ -56,9 +56,11 @@ exports.startup = function() {
|
||||
srcDocument.write("<!DOCTYPE html><head></head><body class='tc-body tc-single-tiddler-window'></body></html>");
|
||||
srcDocument.close();
|
||||
srcDocument.title = windowTitle;
|
||||
$tw.eventBus.emit("window:opened",{windowID, window: srcWindow});
|
||||
srcWindow.addEventListener("beforeunload",function(event) {
|
||||
delete $tw.windows[windowID];
|
||||
$tw.wiki.removeEventListener("change",refreshHandler);
|
||||
$tw.eventBus.emit("window:closed",{windowID});
|
||||
},false);
|
||||
// Set up the styles
|
||||
var styleWidgetNode = $tw.wiki.makeTranscludeWidget("$:/core/ui/PageStylesheet",{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20140720164948099
|
||||
modified: 20201124185829706
|
||||
modified: 20250819181815032
|
||||
tags: Mechanisms
|
||||
title: InfoMechanism
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -19,6 +19,7 @@ System tiddlers in the namespace `$:/info/` are used to expose information about
|
||||
|[[$:/info/browser/language]] |<<.from-version "5.1.20">> Language as reported by browser (note that some browsers report two character codes such as `en` while others report full codes such as `en-GB`) |
|
||||
|[[$:/info/browser/screen/width]] |Screen width in pixels |
|
||||
|[[$:/info/browser/screen/height]] |Screen height in pixels |
|
||||
|`$:/info/browser/window/*` |<<.from-version "5.4.0">> Tiddlers reporting window dimensions, updated when the windows are resized |
|
||||
|[[$:/info/node]] |Running under [[Node.js]]? ("yes" or "no") |
|
||||
|[[$:/info/url/full]] |<<.from-version "5.1.14">> Full URL of wiki (eg, ''<<example full>>'') |
|
||||
|[[$:/info/url/host]] |<<.from-version "5.1.14">> Host portion of URL of wiki (eg, ''<<example host>>'') |
|
||||
@@ -29,3 +30,27 @@ System tiddlers in the namespace `$:/info/` are used to expose information about
|
||||
|[[$:/info/url/protocol]] |<<.from-version "5.1.14">> Protocol portion of URL of wiki (eg, ''<<example protocol>>'') |
|
||||
|[[$:/info/url/search]] |<<.from-version "5.1.14">> Search portion of URL of wiki (eg, ''<<example search>>'') |
|
||||
|[[$:/info/darkmode]] |<<.from-version "5.1.23">> Is dark mode enabled? ("yes" or "no") |
|
||||
|
||||
! Main Window Dimension Tiddlers
|
||||
|
||||
<<.from-version "5.4.0">> These tiddlers reports the dimensions of the main ~TiddlyWiki window and are updated automatically whenever the main window is resized.
|
||||
|
||||
|!Title |!Description |
|
||||
|[[$:/info/browser/window/system/main/outer/width]] |Full browser window including chrome, tabs, toolbars |
|
||||
|[[$:/info/browser/window/system/main/outer/height]] |Full browser window including chrome, tabs, toolbars |
|
||||
|[[$:/info/browser/window/system/main/inner/width]] |Viewport width including scrollbars |
|
||||
|[[$:/info/browser/window/system/main/inner/height]] |Viewport height including scrollbars |
|
||||
|[[$:/info/browser/window/system/main/client/width]] |Content width excluding scrollbars |
|
||||
|[[$:/info/browser/window/system/main/client/height]] |Content height excluding scrollbars |
|
||||
|
||||
! User-Created Window Dimension Tiddlers
|
||||
|
||||
<<.from-version "5.4.0">> These tiddler reports the dimensions of additional windows opened via [[tm-open-window|WidgetMessage: tm-open-window]]. The windowID used when opening the window is used to identify the corresponding info tiddlers. These tiddlers are updated automatically whenever the main window is resized.
|
||||
|
||||
|!Title |!Description |
|
||||
|`$:/info/browser/window/user/<windowID>/outer/width` | Full browser window including chrome, tabs, toolbars |
|
||||
|`$:/info/browser/window/user/<windowID>/outer/height` | Full browser window including chrome, tabs, toolbars |
|
||||
|`$:/info/browser/window/user/<windowID>/inner/width` |Viewport width including scrollbars |
|
||||
|`$:/info/browser/window/user/<windowID>/inner/height` |Viewport height including scrollbars |
|
||||
|`$:/info/browser/window/user/<windowID>/client/width` |Content width excluding scrollbars |
|
||||
|`$:/info/browser/window/user/<windowID>/client/height` |Content height excluding scrollbars |
|
||||
|
||||
Reference in New Issue
Block a user