@@ -13,6 +13,9 @@ const customSqlTypePrefix = 'Standard.Database.Data.Sql.Sql_Type.'
1313/** Specifies opacity of interpolation background color. */
1414const interpolationBacgroundOpacity = 0.3
1515
16+ /** A regular expression for parsing CSS transforms. */
17+ const matrixRegex = / m a t r i x ( 3 d ) ? \( .* ?\) /
18+
1619/** The CSS styles for the visualization. */
1720const visualizationStyle = `
1821 <style>
@@ -80,15 +83,15 @@ loadScript('https://cdnjs.cloudflare.com/ajax/libs/sql-formatter/4.0.2/sql-forma
8083 * interpolated query parameters.
8184 */
8285class SqlVisualization extends Visualization {
83- // TODO Change the type below once #837 is done:
84- // 'Standard.Database.Data.Table.Table | Standard.Database.Data.Column.Column'
8586 static inputType = 'Standard.Database.Data.Table.Table | Standard.Database.Data.Column.Column'
86- static label = 'SQL Query'
87+ static label = 'SQL Query (dev) '
8788
8889 constructor ( api ) {
8990 super ( api )
9091 this . setPreprocessorModule ( 'Standard.Visualization.Sql.Visualization' )
9192 this . setPreprocessorCode ( `x -> here.prepare_visualization x` )
93+
94+ this . tooltip = null
9295 }
9396
9497 onDataReceived ( data ) {
@@ -126,7 +129,10 @@ class SqlVisualization extends Visualization {
126129 containers . scrollable . innerHTML = visHtml
127130 this . dom . appendChild ( parentContainer )
128131
129- const tooltip = new Tooltip ( parentContainer )
132+ const tooltipParent = document . querySelector ( '#root > .scene > .front > .view_projection' )
133+ console . log ( tooltipParent )
134+ const tooltip = new Tooltip ( tooltipParent )
135+ this . tooltip = tooltip
130136 const baseMismatches = this . dom . getElementsByClassName ( 'mismatch' )
131137 const extendedMismatchAreas = this . dom . getElementsByClassName ( 'mismatch-mouse-area' )
132138 setupMouseInteractionForMismatches ( tooltip , baseMismatches )
@@ -142,6 +148,7 @@ class SqlVisualization extends Visualization {
142148 while ( this . dom . firstChild ) {
143149 this . dom . removeChild ( this . dom . lastChild )
144150 }
151+ this . removeTooltip ( )
145152 }
146153
147154 /**
@@ -170,6 +177,18 @@ class SqlVisualization extends Visualization {
170177 }
171178 }
172179
180+ onHide ( ) {
181+ this . removeTooltip ( )
182+ }
183+
184+ /** Removes the tooltip element, if it has been created. */
185+ removeTooltip ( ) {
186+ if ( this . tooltip !== null ) {
187+ this . tooltip . destroy ( )
188+ this . tooltip = null
189+ }
190+ }
191+
173192 setSize ( size ) {
174193 this . dom . setAttributeNS ( null , 'width' , size [ 0 ] )
175194 this . dom . setAttributeNS ( null , 'height' , size [ 1 ] )
@@ -372,6 +391,10 @@ class Tooltip {
372391 * ignored.
373392 */
374393 hide ( actor ) {
394+ if ( this . tooltip == null ) {
395+ console . log ( 'hide called on destroyed tooltip' )
396+ return
397+ }
375398 if ( this . tooltipOwner === null || this . tooltipOwner == actor ) {
376399 this . tooltipOwner = null
377400 this . tooltip . style . opacity = 0
@@ -384,6 +407,11 @@ class Tooltip {
384407 * Tooltip content is specified by the `message` which can include arbitrary HTML.
385408 */
386409 show ( actor , message ) {
410+ if ( this . tooltip == null ) {
411+ console . log ( 'show called on destroyed tooltip' )
412+ return
413+ }
414+
387415 this . tooltipOwner = actor
388416 this . tooltip . innerHTML = message
389417 this . tooltip . style . opacity = 1
@@ -393,7 +421,7 @@ class Tooltip {
393421 const scrollElement = codeContainer . parentElement
394422
395423 const scrollOffsetX = scrollElement . scrollLeft
396- const scrollOffsetY = scrollElement . scrollTop + scrollElement . offsetHeight
424+ const scrollOffsetY = scrollElement . scrollTop
397425
398426 const interpolantOffsetX = interpolantContainer . offsetLeft
399427 const interpolantOffsetY = interpolantContainer . offsetTop
@@ -402,11 +430,37 @@ class Tooltip {
402430 const belowPadding = 3
403431 const belowOffset = interpolantContainer . offsetHeight + belowPadding
404432
405- const x = interpolantOffsetX - scrollOffsetX + centeringOffset
406- const y = interpolantOffsetY - scrollOffsetY + belowOffset
433+ const visualization = actor . closest ( '.visualization' )
434+ const visMatrix = getMatrix ( visualization )
435+
436+ const x = visMatrix . m41 + interpolantOffsetX - scrollOffsetX + centeringOffset
437+ const y = visMatrix . m42 + interpolantOffsetY - scrollOffsetY + belowOffset
407438
408439 this . tooltip . style . transform = 'translate(' + x + 'px, ' + y + 'px)'
409440 }
441+
442+ /** Removes the element itself.
443+ *
444+ * The tooltip instance is not usable after this has been called.
445+ */
446+ destroy ( ) {
447+ this . tooltipOwner = null
448+ if ( this . tooltip == null ) {
449+ console . log ( 'destroy called twice on a tooltip' )
450+ return
451+ }
452+ this . tooltip . remove ( )
453+ this . tooltip = null
454+ }
455+ }
456+
457+ /** A helper function that returns a parsed CSS transformation matrix for a given element. */
458+ function getMatrix ( element ) {
459+ const transform = window . getComputedStyle ( element ) . transform
460+ console . log ( transform )
461+ const matrixString = transform . match ( matrixRegex ) [ 0 ]
462+ const matrix = new DOMMatrix ( matrixString )
463+ return matrix
410464}
411465
412466/**
0 commit comments