Fossil SCM
pikchr: experimentally only show the source/svg and copy buttons when the mouse is over the pikchr area or the user taps on it (which toggles the buttons). This allows us to make them a bit bigger and keeps them from blocking nearby UI elements when they're not needed.
Commit
460376e6a44fd956f5913836b5c54128d5eda04b40fc2abe3741760dff4b738b
Parent
a35126bf289da01…
2 files changed
+3
-1
+30
-6
+3
-1
| --- src/fossil.copybutton.js | ||
| +++ src/fossil.copybutton.js | ||
| @@ -98,11 +98,13 @@ | ||
| 98 | 98 | undefined===srcElem.value ? ()=>srcElem.innerText : ()=>srcElem.value |
| 99 | 99 | ); |
| 100 | 100 | D.copyStyle(e, opt.style); |
| 101 | 101 | e.addEventListener( |
| 102 | 102 | 'click', |
| 103 | - function(){ | |
| 103 | + function(ev){ | |
| 104 | + ev.preventDefault(); | |
| 105 | + ev.stopPropagation(); | |
| 104 | 106 | if(e.classList.contains('disabled')) return; |
| 105 | 107 | const txt = extract.call(opt); |
| 106 | 108 | if(txt && D.copyTextToClipboard(txt)){ |
| 107 | 109 | e.dispatchEvent(new CustomEvent('text-copied',{ |
| 108 | 110 | detail: {text: txt} |
| 109 | 111 |
| --- src/fossil.copybutton.js | |
| +++ src/fossil.copybutton.js | |
| @@ -98,11 +98,13 @@ | |
| 98 | undefined===srcElem.value ? ()=>srcElem.innerText : ()=>srcElem.value |
| 99 | ); |
| 100 | D.copyStyle(e, opt.style); |
| 101 | e.addEventListener( |
| 102 | 'click', |
| 103 | function(){ |
| 104 | if(e.classList.contains('disabled')) return; |
| 105 | const txt = extract.call(opt); |
| 106 | if(txt && D.copyTextToClipboard(txt)){ |
| 107 | e.dispatchEvent(new CustomEvent('text-copied',{ |
| 108 | detail: {text: txt} |
| 109 |
| --- src/fossil.copybutton.js | |
| +++ src/fossil.copybutton.js | |
| @@ -98,11 +98,13 @@ | |
| 98 | undefined===srcElem.value ? ()=>srcElem.innerText : ()=>srcElem.value |
| 99 | ); |
| 100 | D.copyStyle(e, opt.style); |
| 101 | e.addEventListener( |
| 102 | 'click', |
| 103 | function(ev){ |
| 104 | ev.preventDefault(); |
| 105 | ev.stopPropagation(); |
| 106 | if(e.classList.contains('disabled')) return; |
| 107 | const txt = extract.call(opt); |
| 108 | if(txt && D.copyTextToClipboard(txt)){ |
| 109 | e.dispatchEvent(new CustomEvent('text-copied',{ |
| 110 | detail: {text: txt} |
| 111 |
+30
-6
| --- src/fossil.pikchr.js | ||
| +++ src/fossil.pikchr.js | ||
| @@ -10,18 +10,18 @@ | ||
| 10 | 10 | // Install an app-specific stylesheet, just for development, after which |
| 11 | 11 | // it will be moved into default.css |
| 12 | 12 | (function(){ |
| 13 | 13 | const head = document.head || document.querySelector('head'), |
| 14 | 14 | styleTag = document.createElement('style'), |
| 15 | - wh = '1em' /* fixed width/height of buttons */, | |
| 15 | + wh = '1.5em' /* fixed width/height of buttons */, | |
| 16 | 16 | styleCSS = ` |
| 17 | 17 | .pikchr-src-button { |
| 18 | 18 | min-height: ${wh}; max-height: ${wh}; |
| 19 | 19 | min-width: ${wh}; max-width: ${wh}; |
| 20 | 20 | font-size: ${wh}; |
| 21 | 21 | position: absolute; |
| 22 | - top: calc(-${wh} / 2); | |
| 22 | + top: 0; | |
| 23 | 23 | left: 0; |
| 24 | 24 | border: 1px solid black; |
| 25 | 25 | background-color: rgba(255,255,0,0.2); |
| 26 | 26 | border-radius: 0.25cm; |
| 27 | 27 | z-index: 50; |
| @@ -46,12 +46,12 @@ | ||
| 46 | 46 | .pikchr-copy-button { |
| 47 | 47 | min-width: ${wh}; max-width: ${wh}; |
| 48 | 48 | min-height: ${wh}; max-height: ${wh}; |
| 49 | 49 | display: inline-block; |
| 50 | 50 | position: absolute; |
| 51 | - top: calc(-${wh} / 2); | |
| 52 | - left: calc(${wh} * 1.5); | |
| 51 | + top: calc(${wh} * 2); | |
| 52 | + left: 0; | |
| 53 | 53 | z-index: 50; |
| 54 | 54 | padding: 0; margin: 0; |
| 55 | 55 | } |
| 56 | 56 | `; |
| 57 | 57 | head.appendChild(styleTag); |
| @@ -132,12 +132,36 @@ | ||
| 132 | 132 | ? svg.outerHTML |
| 133 | 133 | : srcView.value); |
| 134 | 134 | } |
| 135 | 135 | } |
| 136 | 136 | ); |
| 137 | - D.append(parent, D.addClass(srcView, 'hidden'), btnFlip, btnCopy); | |
| 138 | - btnFlip.addEventListener('click', function f(){ | |
| 137 | + const buttons = [btnFlip, btnCopy]; | |
| 138 | + D.addClass(buttons, 'hidden'); | |
| 139 | + D.append(parent, D.addClass(srcView, 'hidden'), buttons); | |
| 140 | + | |
| 141 | + /** | |
| 142 | + Toggle the buttons on only when the mouse is in the parent | |
| 143 | + widget's area or the user taps on that area. This seems much | |
| 144 | + less "busy" than having them always visible and slightly in the way. | |
| 145 | + It also means that we can make them a bit larger. | |
| 146 | + */ | |
| 147 | + parent.addEventListener('mouseenter', function(ev){ | |
| 148 | + if(ev.target === parent) D.removeClass(buttons, 'hidden'); | |
| 149 | + }, true); | |
| 150 | + parent.addEventListener('mouseleave', function(ev){ | |
| 151 | + if(ev.target === parent) D.addClass(buttons, 'hidden'); | |
| 152 | + }, true); | |
| 153 | + /* mouseenter/leave work well... but only if there's a mouse. */ | |
| 154 | + parent.addEventListener('click', function(ev){ | |
| 155 | + ev.preventDefault(); | |
| 156 | + ev.stopPropagation(); | |
| 157 | + D.toggleClass(buttons, 'hidden'); | |
| 158 | + }, false); | |
| 159 | + | |
| 160 | + btnFlip.addEventListener('click', function f(ev){ | |
| 161 | + ev.preventDefault(); | |
| 162 | + ev.stopPropagation(); | |
| 139 | 163 | if(!f.hasOwnProperty('origMaxWidth')){ |
| 140 | 164 | f.origMaxWidth = parent.style.maxWidth; |
| 141 | 165 | } |
| 142 | 166 | const svgStyle = window.getComputedStyle(svg); |
| 143 | 167 | srcView.style.minWidth = svgStyle.width; |
| 144 | 168 |
| --- src/fossil.pikchr.js | |
| +++ src/fossil.pikchr.js | |
| @@ -10,18 +10,18 @@ | |
| 10 | // Install an app-specific stylesheet, just for development, after which |
| 11 | // it will be moved into default.css |
| 12 | (function(){ |
| 13 | const head = document.head || document.querySelector('head'), |
| 14 | styleTag = document.createElement('style'), |
| 15 | wh = '1em' /* fixed width/height of buttons */, |
| 16 | styleCSS = ` |
| 17 | .pikchr-src-button { |
| 18 | min-height: ${wh}; max-height: ${wh}; |
| 19 | min-width: ${wh}; max-width: ${wh}; |
| 20 | font-size: ${wh}; |
| 21 | position: absolute; |
| 22 | top: calc(-${wh} / 2); |
| 23 | left: 0; |
| 24 | border: 1px solid black; |
| 25 | background-color: rgba(255,255,0,0.2); |
| 26 | border-radius: 0.25cm; |
| 27 | z-index: 50; |
| @@ -46,12 +46,12 @@ | |
| 46 | .pikchr-copy-button { |
| 47 | min-width: ${wh}; max-width: ${wh}; |
| 48 | min-height: ${wh}; max-height: ${wh}; |
| 49 | display: inline-block; |
| 50 | position: absolute; |
| 51 | top: calc(-${wh} / 2); |
| 52 | left: calc(${wh} * 1.5); |
| 53 | z-index: 50; |
| 54 | padding: 0; margin: 0; |
| 55 | } |
| 56 | `; |
| 57 | head.appendChild(styleTag); |
| @@ -132,12 +132,36 @@ | |
| 132 | ? svg.outerHTML |
| 133 | : srcView.value); |
| 134 | } |
| 135 | } |
| 136 | ); |
| 137 | D.append(parent, D.addClass(srcView, 'hidden'), btnFlip, btnCopy); |
| 138 | btnFlip.addEventListener('click', function f(){ |
| 139 | if(!f.hasOwnProperty('origMaxWidth')){ |
| 140 | f.origMaxWidth = parent.style.maxWidth; |
| 141 | } |
| 142 | const svgStyle = window.getComputedStyle(svg); |
| 143 | srcView.style.minWidth = svgStyle.width; |
| 144 |
| --- src/fossil.pikchr.js | |
| +++ src/fossil.pikchr.js | |
| @@ -10,18 +10,18 @@ | |
| 10 | // Install an app-specific stylesheet, just for development, after which |
| 11 | // it will be moved into default.css |
| 12 | (function(){ |
| 13 | const head = document.head || document.querySelector('head'), |
| 14 | styleTag = document.createElement('style'), |
| 15 | wh = '1.5em' /* fixed width/height of buttons */, |
| 16 | styleCSS = ` |
| 17 | .pikchr-src-button { |
| 18 | min-height: ${wh}; max-height: ${wh}; |
| 19 | min-width: ${wh}; max-width: ${wh}; |
| 20 | font-size: ${wh}; |
| 21 | position: absolute; |
| 22 | top: 0; |
| 23 | left: 0; |
| 24 | border: 1px solid black; |
| 25 | background-color: rgba(255,255,0,0.2); |
| 26 | border-radius: 0.25cm; |
| 27 | z-index: 50; |
| @@ -46,12 +46,12 @@ | |
| 46 | .pikchr-copy-button { |
| 47 | min-width: ${wh}; max-width: ${wh}; |
| 48 | min-height: ${wh}; max-height: ${wh}; |
| 49 | display: inline-block; |
| 50 | position: absolute; |
| 51 | top: calc(${wh} * 2); |
| 52 | left: 0; |
| 53 | z-index: 50; |
| 54 | padding: 0; margin: 0; |
| 55 | } |
| 56 | `; |
| 57 | head.appendChild(styleTag); |
| @@ -132,12 +132,36 @@ | |
| 132 | ? svg.outerHTML |
| 133 | : srcView.value); |
| 134 | } |
| 135 | } |
| 136 | ); |
| 137 | const buttons = [btnFlip, btnCopy]; |
| 138 | D.addClass(buttons, 'hidden'); |
| 139 | D.append(parent, D.addClass(srcView, 'hidden'), buttons); |
| 140 | |
| 141 | /** |
| 142 | Toggle the buttons on only when the mouse is in the parent |
| 143 | widget's area or the user taps on that area. This seems much |
| 144 | less "busy" than having them always visible and slightly in the way. |
| 145 | It also means that we can make them a bit larger. |
| 146 | */ |
| 147 | parent.addEventListener('mouseenter', function(ev){ |
| 148 | if(ev.target === parent) D.removeClass(buttons, 'hidden'); |
| 149 | }, true); |
| 150 | parent.addEventListener('mouseleave', function(ev){ |
| 151 | if(ev.target === parent) D.addClass(buttons, 'hidden'); |
| 152 | }, true); |
| 153 | /* mouseenter/leave work well... but only if there's a mouse. */ |
| 154 | parent.addEventListener('click', function(ev){ |
| 155 | ev.preventDefault(); |
| 156 | ev.stopPropagation(); |
| 157 | D.toggleClass(buttons, 'hidden'); |
| 158 | }, false); |
| 159 | |
| 160 | btnFlip.addEventListener('click', function f(ev){ |
| 161 | ev.preventDefault(); |
| 162 | ev.stopPropagation(); |
| 163 | if(!f.hasOwnProperty('origMaxWidth')){ |
| 164 | f.origMaxWidth = parent.style.maxWidth; |
| 165 | } |
| 166 | const svgStyle = window.getComputedStyle(svg); |
| 167 | srcView.style.minWidth = svgStyle.width; |
| 168 |