diff --git a/js/macros/chooser.js b/js/macros/chooser.js index 14dd7b52d..3f0e689b3 100644 --- a/js/macros/chooser.js +++ b/js/macros/chooser.js @@ -12,43 +12,86 @@ var Renderer = require("../Renderer.js").Renderer, Tiddler = require("../Tiddler.js").Tiddler, utils = require("../Utils.js"); -function positionChooserPanel(macroNode,x,y) { - var domWrapper = macroNode.domNode, - heightWrapper = domWrapper.offsetHeight, - rectWrapper = domWrapper.getBoundingClientRect(), - domPanel = macroNode.content[0].domNode, - heightPanel = domPanel.offsetHeight, - rectPanel = domPanel.getBoundingClientRect(); - // Make the coordinates relative to the wrapper - x = x - rectWrapper.left; - y = y - rectWrapper.top; - // Scale the panel to fit - var scaleFactor = heightWrapper/heightPanel; - // Scale up as we move right - var expandFactor = ((100+x)/100); - // Set up the transform - var scale = scaleFactor * expandFactor, - translate = (y / scale) - ((y/heightWrapper) * heightPanel); - domPanel.style.webkitTransformOrigin = "0 0"; - domPanel.style.webkitTransform = "scale(" + scale + ") translateY(" + translate + "px)"; +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.store.getTiddler(macroNode.tiddlerTitle)); + macroNode.content = [wrapper]; + macroNode.content[0].renderInDom(macroNode.domNode); + } } -function loadContent(macroNode) { - var nodes = []; - macroNode.store.forEachTiddler("title",function(title,tiddler) { - nodes.push(Renderer.ElementNode("li",{},[ - Renderer.TextNode(title) - ])); - }); - var wrapper = Renderer.ElementNode("ul",{},nodes); - wrapper.execute(macroNode.parents,macroNode.store.getTiddler(macroNode.tiddlerTitle)); - macroNode.content = [wrapper]; - macroNode.content[0].renderInDom(macroNode.domNode); +function select(macroNode,y) { + if(macroNode.content.length > 0) { + var targetIndex = Math.floor(macroNode.content[0].domNode.childNodes.length * (y/macroNode.domNode.offsetHeight)), + target = macroNode.content[0].domNode.childNodes[targetIndex]; + if(target) { + deselect(macroNode); + macroNode.selectedNode = target; + utils.addClass(target,"selected"); + } + } } -function removeContent(macroNode) { - macroNode.domNode.removeChild(macroNode.content[0].domNode); - macroNode.content = []; +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); + } +} + +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 domWrapper = macroNode.domNode, + heightWrapper = domWrapper.offsetHeight, + rectWrapper = domWrapper.getBoundingClientRect(), + domPanel = macroNode.content[0].domNode, + heightPanel = domPanel.offsetHeight, + widthPanel = domPanel.offsetWidth; + // Make the coordinates relative to the wrapper + x = x - rectWrapper.left; + y = y - rectWrapper.top; + // Scale the panel to fit + var scaleFactor = heightWrapper/heightPanel; + // Scale up as we move right + var expandFactor = x > 50 ? (x/50) : 1; + // Set up the transform + var scale = scaleFactor * expandFactor, + translateX = 0, //x > 50 ? 0 : -(((50-x)/50) * widthPanel) / scale, + translateY = (y / scale) - ((y/heightWrapper) * heightPanel); + domPanel.style.webkitTransformOrigin = "0 0"; + domPanel.style.webkitTransform = "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 = { @@ -58,45 +101,51 @@ exports.macro = { }, events: { touchstart: function(event) { - this.domNode.style.backgroundColor = "red"; - loadContent(this); - positionChooserPanel(this,event.touches[0].pageX,event.touches[0].pageY); + showChooser(this); + hoverChooser(this,event.touches[0].clientX,event.touches[0].clientY); event.preventDefault(); return false; }, touchmove: function(event) { - positionChooserPanel(this,event.touches[0].pageX,event.touches[0].pageY); + hoverChooser(this,event.touches[0].clientX,event.touches[0].clientY); event.preventDefault(); return false; }, touchend: function(event) { - this.domNode.style.backgroundColor = "blue"; - removeContent(this); + action(this); + hideChooser(this); event.preventDefault(); return false; }, mouseover: function(event) { if(event.target === this.domNode) { - loadContent(this); - positionChooserPanel(this,event.clientX,event.clientY); + showChooser(this); + hoverChooser(this,event.clientX,event.clientY); event.preventDefault(); return false; } }, mousemove: function(event) { - positionChooserPanel(this,event.clientX,event.clientY); + 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)) { - removeContent(this); + hideChooser(this); event.preventDefault(); return false; } } }, execute: function() { + this.chooserDisplayed = false; return []; } }; diff --git a/tiddlywiki5/styles.css b/tiddlywiki5/styles.css index cfa7c41c2..8bc2c401b 100644 --- a/tiddlywiki5/styles.css +++ b/tiddlywiki5/styles.css @@ -112,13 +112,28 @@ a.tw-tiddlylink-missing { position: absolute; top: 0; left: 0; + min-width: 16px; height: 100%; - background: #ddd; } .navigation-panel div { width: 100%; height: 100%; - padding-left: 8px; - padding-right: 8px; } + +.navigation-panel div ul { + margin: 0 0 0 0; + padding: 0px 4px 0px 4px; + list-style: none; + background: #ddd; +} + +.navigation-panel div ul li { + padding: 2px 4px 2px 4px; +} + +.navigation-panel .selected { + color: #fff; + background: #a55; +} +