mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-09 11:29:58 +00:00
392e717497
Now the title is passed around, rather than a reference to the tiddler. This lets the context be a missing tiddler, enabling us to correctly render missing tiddlers
159 lines
4.3 KiB
JavaScript
159 lines
4.3 KiB
JavaScript
/*\
|
|
title: js/macros/chooser.js
|
|
|
|
\*/
|
|
(function(){
|
|
|
|
/*jslint node: true, browser: true */
|
|
"use strict";
|
|
|
|
var Renderer = require("../Renderer.js").Renderer,
|
|
Dependencies = require("../Dependencies.js").Dependencies,
|
|
Tiddler = require("../Tiddler.js").Tiddler,
|
|
utils = require("../Utils.js");
|
|
|
|
function showChooser(macroNode) {
|
|
if(!macroNode.chooserDisplayed) {
|
|
macroNode.chooserDisplayed = true;
|
|
var nodes = [];
|
|
macroNode.store.forEachTiddler("title",function(title,tiddler) {
|
|
nodes.push(Renderer.ElementNode("li",{
|
|
"data-link": title
|
|
},[
|
|
Renderer.TextNode(title)
|
|
]));
|
|
});
|
|
var wrapper = Renderer.ElementNode("ul",{},nodes);
|
|
wrapper.execute(macroNode.parents,macroNode.tiddlerTitle);
|
|
macroNode.content = [wrapper];
|
|
macroNode.content[0].renderInDom(macroNode.domNode);
|
|
}
|
|
}
|
|
|
|
/*
|
|
Select the appropriate chooser item given a touch/mouse position in screen coordinates
|
|
*/
|
|
function select(macroNode,y) {
|
|
if(macroNode.content.length > 0) {
|
|
var targetIndex = Math.floor(macroNode.content[0].domNode.childNodes.length * (y/window.innerHeight)),
|
|
target = macroNode.content[0].domNode.childNodes[targetIndex];
|
|
if(target) {
|
|
deselect(macroNode);
|
|
macroNode.selectedNode = target;
|
|
utils.addClass(target,"selected");
|
|
}
|
|
}
|
|
}
|
|
|
|
function deselect(macroNode) {
|
|
if(macroNode.selectedNode) {
|
|
utils.removeClass(macroNode.selectedNode,"selected");
|
|
macroNode.selectedNode = null;
|
|
}
|
|
}
|
|
|
|
function action(macroNode) {
|
|
if(macroNode.selectedNode) {
|
|
var navEvent = document.createEvent("Event");
|
|
navEvent.initEvent("tw-navigate",true,true);
|
|
navEvent.navigateTo = macroNode.selectedNode.getAttribute("data-link");
|
|
macroNode.domNode.dispatchEvent(navEvent);
|
|
}
|
|
}
|
|
|
|
/*
|
|
Set the position of the chooser panel within its wrapper given a touch/mouse position in screen coordinates
|
|
*/
|
|
function hoverChooser(macroNode,x,y) {
|
|
if(macroNode.chooserDisplayed) {
|
|
// Get the target element that the touch/mouse is over
|
|
select(macroNode,y);
|
|
// Things we need for sizing and positioning the chooser
|
|
var domPanel = macroNode.content[0].domNode,
|
|
heightPanel = domPanel.offsetHeight,
|
|
widthPanel = domPanel.offsetWidth;
|
|
// Position the chooser div to account for scrolling
|
|
macroNode.content[0].domNode.style.top = window.pageYOffset + "px";
|
|
// Scale the panel to fit
|
|
var scaleFactor = window.innerHeight/heightPanel;
|
|
// Scale up as we move right
|
|
var expandFactor = x > 50 ? ((x+150)/200) : 1;
|
|
// Set up the transform
|
|
var scale = scaleFactor * expandFactor,
|
|
translateX = x > 16 ? 0 : -(((16-x)/16) * widthPanel) / scale,
|
|
translateY = (y / scale) - ((y/window.innerHeight) * heightPanel);
|
|
domPanel.style.webkitTransformOrigin =
|
|
domPanel.style.MozTransformOrigin = "0 0";
|
|
domPanel.style.webkitTransform =
|
|
domPanel.style.MozTransform = "scale(" + scale + ") translateX(" + translateX + "px) translateY(" + translateY + "px)";
|
|
}
|
|
}
|
|
|
|
function hideChooser(macroNode) {
|
|
if(macroNode.chooserDisplayed) {
|
|
deselect(macroNode);
|
|
macroNode.chooserDisplayed = false;
|
|
macroNode.domNode.removeChild(macroNode.content[0].domNode);
|
|
macroNode.content = [];
|
|
}
|
|
}
|
|
|
|
exports.macro = {
|
|
name: "chooser",
|
|
wrapperTag: "div",
|
|
params: {
|
|
},
|
|
events: {
|
|
touchstart: function(event) {
|
|
showChooser(this);
|
|
hoverChooser(this,event.touches[0].clientX,event.touches[0].clientY);
|
|
event.preventDefault();
|
|
return false;
|
|
},
|
|
touchmove: function(event) {
|
|
hoverChooser(this,event.touches[0].clientX,event.touches[0].clientY);
|
|
event.preventDefault();
|
|
return false;
|
|
},
|
|
touchend: function(event) {
|
|
action(this);
|
|
hideChooser(this);
|
|
event.preventDefault();
|
|
return false;
|
|
},
|
|
mouseover: function(event) {
|
|
if(event.target === this.domNode) {
|
|
showChooser(this);
|
|
hoverChooser(this,event.clientX,event.clientY);
|
|
event.preventDefault();
|
|
return false;
|
|
}
|
|
},
|
|
mousemove: function(event) {
|
|
hoverChooser(this,event.clientX,event.clientY);
|
|
event.preventDefault();
|
|
return false;
|
|
},
|
|
mouseup: function(event) {
|
|
action(this);
|
|
hideChooser(this);
|
|
event.preventDefault();
|
|
return false;
|
|
},
|
|
mouseout: function(event) {
|
|
if(!utils.domContains(this.domNode,event.relatedTarget)) {
|
|
hideChooser(this);
|
|
event.preventDefault();
|
|
return false;
|
|
}
|
|
}
|
|
},
|
|
execute: function() {
|
|
this.chooserDisplayed = false;
|
|
return [];
|
|
}
|
|
};
|
|
|
|
})();
|
|
|