module Webglimpse { interface ExampleTooltip { show ( html , i , j ) ; move ( i , j ) ; hide ( ) ; } function newExampleTooltip ( ) { var div = document . createElement ( 'div' ) ; div . classList . add ( 'exampleTooltip' ) ; div . style . position = 'absolute' ; div . style . zIndex = '1' ; div . style . visibility = 'hidden' ; document . body . appendChild ( div ) ; return { show : function ( html , i , j ) { div . innerHTML = html ; div . style . left = ( i ) + 'px' ; div . style . bottom = ( j - div . clientHeight ) + 'px' ; div . style . visibility = 'visible' ; } , move : function ( i , j ) { div . style . left = ( i ) + 'px' ; div . style . bottom = ( j - div . clientHeight ) + 'px' ; } , hide : function ( ) { div . style . visibility = 'hidden' ; } } ; } export function runTimelineExample ( container ) { var canvas = document . createElement ( 'canvas' ) ; canvas . id = 'exampleCanvas' ; canvas . style . padding = '0' ; container . appendChild ( canvas ) ; var drawable = newDrawable ( canvas ) ; var updateCanvasSize = function ( ) { $ ( canvas ) . height ( $ ( window ) . height ( ) - canvas . getBoundingClientRect ( ) . top ) ; canvas . width = $ ( canvas ) . width ( ) ; canvas . height = $ ( canvas ) . height ( ) ; drawable . redraw ( ) ; } ; $ ( window ) . resize ( updateCanvasSize ) ; updateCanvasSize ( ) ; var timeAxis = new TimeAxis1D ( parseTime_PMILLIS ( '2014-01-01T00:00:00Z' ) , parseTime_PMILLIS ( '2014-01-01T12:00:00Z' ) ) ; timeAxis . limitsChanged . on ( drawable . redraw ) ; var timelineOptions = { selectedIntervalMode : 'single' , topTimeZone : '-0500' , fgColor : white , rowLabelColor : white , groupLabelColor : white , axisLabelColor : white , bgColor : rgb ( 0.098 , 0.165 , 0.243 ) , rowBgColor : rgb ( 0.020 , 0.086 , 0.165 ) , rowAltBgColor : rgb ( 0.020 , 0.086 , 0.165 ) , gridColor : gray ( 0.5 ) , selectedIntervalFillColor : rgba ( 0 , 0.6 , 0.8 , 0.157 ) , selectedIntervalBorderColor : rgb ( 0 , 0.2 , 1.0 ) , allowEventMultiSelection : true , rowPaneFactoryChooser : rowPaneFactoryChooser_THIN } ; var model = new TimelineModel ( ) ; var ui = new TimelineUi ( model , { allowEventMultiSelection : true } ) ; var timelinePane = newTimelinePane ( drawable , timeAxis , model , timelineOptions , ui ) ; var selection = ui . selection ; selection . selectedInterval . setInterval ( parseTime_PMILLIS ( '2014-01-01T08:30:00Z' ) , parseTime_PMILLIS ( '2014-01-01T08:50:00Z' ) ) ; var contentPane = new Pane ( newCornerLayout ( Side . LEFT , Side . TOP ) ) ; contentPane . addPane ( timelinePane ) ; drawable . setContentPane ( newInsetPane ( contentPane , newInsets ( 12 , 10 , 2 ) , timelineOptions . bgColor ) ) ; drawable . redraw ( ) ; $ . getJSON ( 'timelineUi.json' , function ( uiStyles ) { uiStyles . eventStyles . forEach ( function ( s ) { ui . eventStyles . add ( new TimelineEventStyleUi ( s ) ) ; } ) ; uiStyles . annotationStyles . forEach ( function ( s ) { ui . annotationStyles . add ( new TimelineAnnotationStyleUi ( s ) ) ; } ) ; } ) ; var timeStep = hoursToMillis ( 1 ) ; var selectedInterval = selection . selectedInterval ; var a = document . getElementById ( 'selected-time-step-backward' ) ; a . onclick = function ( ) { selectedInterval . pan ( - timeStep ) ; if ( selectedInterval . start_PMILLIS < timeAxis . tMin_PMILLIS ) { var tSize_MILLIS = timeAxis . tSize_MILLIS ; timeAxis . tMin_PMILLIS = selectedInterval . start_PMILLIS ; timeAxis . tMax_PMILLIS = timeAxis . tMin_PMILLIS + tSize_MILLIS ; } drawable . redraw ( ) ; } ; var a = document . getElementById ( 'selected-time-step-forward' ) ; a . onclick = function ( ) { selectedInterval . pan ( timeStep ) ; if ( selectedInterval . end_PMILLIS > timeAxis . tMax_PMILLIS ) { var tSize_MILLIS = timeAxis . tSize_MILLIS ; timeAxis . tMax_PMILLIS = selectedInterval . end_PMILLIS ; timeAxis . tMin_PMILLIS = timeAxis . tMax_PMILLIS - tSize_MILLIS ; } drawable . redraw ( ) ; } ; var a = document . getElementById ( 'selected-time-decrease' ) ; a . onclick = function ( ) { var newDuration_MILLIS = Math . max ( selectedInterval . duration_MILLIS - timeStep , timeStep ) ; selectedInterval . start_PMILLIS = selectedInterval . end_PMILLIS - newDuration_MILLIS ; drawable . redraw ( ) ; } ; var a = document . getElementById ( 'selected-time-increase' ) ; a . onclick = function ( ) { var newDuration_MILLIS = Math . max ( selectedInterval . duration_MILLIS + timeStep , timeStep ) ; selectedInterval . start_PMILLIS = selectedInterval . end_PMILLIS - newDuration_MILLIS ; drawable . redraw ( ) ; } ; var a = document . getElementById ( 'selected-time-calendar' ) ; a . onclick = function ( ) { var dateFormat = 'M/D/YYYY' ; var id = 'calendar1' ; var calendardiv = document . getElementById ( id ) ; if ( ! calendardiv ) { calendardiv = document . createElement ( 'div' ) ; calendardiv . style . fontSize = '12' ; var rect = a . getBoundingClientRect ( ) ; var position = [ rect . left , rect . bottom - 4 ] ; var options = { } ; var callback = function ( date , picker ) { var newTime = moment ( date , dateFormat ) . valueOf ( ) ; var selectionDiff = selectedInterval . end_PMILLIS - selectedInterval . start_PMILLIS ; var axisDiff = timeAxis . tMax_PMILLIS - timeAxis . tMin_PMILLIS ; selectedInterval . start_PMILLIS = newTime - selectionDiff ; selectedInterval . end_PMILLIS = newTime ; timeAxis . tMin_PMILLIS = newTime - axisDiff ; timeAxis . tMax_PMILLIS = newTime ; drawable . redraw ( ) ; } ; var date = moment ( selectedInterval . start_PMILLIS ) . format ( dateFormat ) ; $ ( calendardiv ) . datepicker ( 'dialog' , date , callback , options , position ) ; } } ; var a = document . getElementById ( 'maximize-button' ) ; a . onclick = function ( ) { if ( model . root . maximizedRowGuids . hasValue ( 'metsci.timelineExample.row03a' ) ) { model . root . maximizedRowGuids . removeValue ( 'metsci.timelineExample.row03a' ) ; } else { model . root . maximizedRowGuids . add ( 'metsci.timelineExample.row03a' ) ; } if ( model . root . maximizedRowGuids . hasValue ( 'metsci.timelineExample.dynamicRow02' ) ) { model . root . maximizedRowGuids . removeValue ( 'metsci.timelineExample.dynamicRow02' ) ; } else { model . root . maximizedRowGuids . add ( 'metsci.timelineExample.dynamicRow02' ) ; } } ; ui . rowUis . valueAdded . on ( function ( rowUi ) { rowUi . panes . valueAdded . on ( function ( pane , index ) { var id = rowUi . panes . idAt ( index ) ; if ( id === 'maximized-label' ) { pane . mouseDown . on ( function ( event ) { if ( event . clickCount === 2 ) { model . root . maximizedRowGuids . removeValue ( rowUi . rowGuid ) ; } } ) ; } else if ( id . search ( '-label$' ) !== - 1 ) { pane . mouseDown . on ( function ( event ) { if ( event . clickCount === 2 ) { model . root . maximizedRowGuids . add ( rowUi . rowGuid ) ; } } ) ; } } ) ; } ) ; var a = document . getElementById ( 'pin-button' ) ; a . onclick = function ( ) { if ( model . root . topPinnedRowGuids . hasValue ( 'metsci.timelineExample.row01a' ) ) { model . root . topPinnedRowGuids . removeValue ( 'metsci.timelineExample.row01a' ) ; } else { model . root . topPinnedRowGuids . add ( 'metsci.timelineExample.row01a' ) ; } if ( model . root . topPinnedRowGuids . hasValue ( 'metsci.timelineExample.row01b' ) ) { model . root . topPinnedRowGuids . removeValue ( 'metsci.timelineExample.row01b' ) ; } else { model . root . topPinnedRowGuids . add ( 'metsci.timelineExample.row01b' ) ; } if ( model . root . bottomPinnedRowGuids . hasValue ( 'metsci.timelineExample.row03a' ) ) { model . root . bottomPinnedRowGuids . removeValue ( 'metsci.timelineExample.row03a' ) ; } else { model . root . bottomPinnedRowGuids . add ( 'metsci.timelineExample.row03a' ) ; } } ; var customRowHeight = 135 ; var a = document . getElementById ( 'flag-button' ) ; a . onclick = function ( ) { customRowHeight = customRowHeight + 10 ; if ( customRowHeight > 200 ) customRowHeight = 135 ; model . row ( 'metsci.timelineExample.row03a' ) . rowHeight = customRowHeight ; model . rows . forEach ( function ( row ) { row . eventGuids . removeValue ( 'metsci.timelineExample.event01' ) ; } ) ; model . events . removeId ( 'metsci.timelineExample.event01' ) ; drawable . redraw ( ) ; } ; var tooltip = newExampleTooltip ( ) ; var iTooltipOffset = + 12 ; var jTooltipOffset = - 12 ; selection . hoveredEvent . changed . on ( function ( ) { var hoveredEvent = selection . hoveredEvent . value ; if ( hoveredEvent ) { var iMouse = selection . mousePos . x ; var jMouse = selection . mousePos . y ; if ( isNumber ( iMouse ) && isNumber ( jMouse ) ) { var html = hoveredEvent . label ; tooltip . show ( html , iMouse + iTooltipOffset , jMouse + jTooltipOffset ) ; } else { tooltip . hide ( ) ; } } else { tooltip . hide ( ) ; } } ) ; selection . mousePos . changed . on ( function ( ) { var iMouse = selection . mousePos . x ; var jMouse = selection . mousePos . y ; if ( isNumber ( iMouse ) && isNumber ( jMouse ) ) { tooltip . move ( iMouse + iTooltipOffset , jMouse + jTooltipOffset ) ; } else { tooltip . hide ( ) ; } } ) ; var hoveredFragment ; var updateTimeseriesTooltip = function ( ) { if ( hasval ( hoveredFragment ) ) { hoveredFragment . dataChanged . off ( updateTimeseriesTooltip ) ; } hoveredFragment = selection . hoveredTimeseries . fragment ; if ( hasval ( hoveredFragment ) ) { hoveredFragment . dataChanged . on ( updateTimeseriesTooltip ) ; var iMouse = selection . mousePos . x ; var jMouse = selection . mousePos . y ; if ( isNumber ( iMouse ) && isNumber ( jMouse ) ) { var html = '' + selection . hoveredTimeseries . data . toFixed ( 2 ) ; tooltip . show ( html , iMouse + iTooltipOffset , jMouse + jTooltipOffset ) ; } else { tooltip . hide ( ) ; } } else { tooltip . hide ( ) ; } } ; selection . hoveredTimeseries . changed . on ( updateTimeseriesTooltip ) ; selection . hoveredAnnotation . changed . on ( function ( ) { if ( hasval ( selection . hoveredAnnotation . value ) ) { } } ) ; selection . hoveredTimeseries . changed . on ( function ( ) { if ( hasval ( selection . hoveredTimeseries . fragment ) ) { var dataValue = selection . hoveredTimeseries . data ; var time_PMILLIS = selection . hoveredTimeseries . times_PMILLIS ; } } ) ; selection . mousePos . changed . on ( function ( ) { var iMouse = selection . mousePos . x ; var jMouse = selection . mousePos . y ; } ) ; selection . hoveredTime_PMILLIS . changed . on ( function ( ) { var hoveredTime_PMILLIS = selection . hoveredTime_PMILLIS . value ; } ) ; selection . selectedInterval . changed . on ( function ( ) { var selectionStart_PMILLIS = selection . selectedInterval . start_PMILLIS ; var selectionEnd_PMILLIS = selection . selectedInterval . end_PMILLIS ; } ) ; selection . hoveredRow . changed . on ( function ( ) { var hoveredRow = selection . hoveredRow . value ; } ) ; selection . hoveredEvent . changed . on ( function ( ) { var hoveredEvent = selection . hoveredEvent . value ; } ) ; selection . selectedEvents . valueAdded . on ( function ( event ) { } ) ; selection . selectedEvents . valueRemoved . on ( function ( event ) { } ) ; var group4 = { groupGuid : 'metsci.timelineExample.group04' , label : 'Group #4' , rowGuids : [ ] } ; model . groups . add ( new TimelineGroupModel ( group4 ) ) ; model . root . groupGuids . add ( group4 . groupGuid ) ; var row = { rowGuid : 'metsci.timelineExample.dynamicRow01' , label : 'Broadband' , eventGuids : [ ] } ; model . rows . add ( new TimelineRowModel ( row ) ) ; model . group ( group4 . groupGuid ) . rowGuids . add ( row . rowGuid ) ; var row = { rowGuid : 'metsci.timelineExample.dynamicRow02' , label : 'Heatmap' , eventGuids : [ ] } ; model . rows . add ( new TimelineRowModel ( row ) ) ; model . group ( group4 . groupGuid ) . rowGuids . add ( row . rowGuid ) ; var fragment3 = new TimelineTimeseriesFragmentModel ( { fragmentGuid : 'metsci.timelineExample.fragment03' } ) ; model . timeseriesFragments . add ( fragment3 ) ; fragment3 . dataChanged . on ( function ( startIndex , endIndex ) { for ( var i = startIndex ; i < endIndex ; i ++ ) { if ( fragment3 . data [ i ] > 20 ) { fragment3 . setData ( i , 20 ) ; } } } ) ; $ . getJSON ( 'heatmapData.json' , function ( json ) { var angleMin = json . minY ; var angleMax = json . maxY ; var timeMin = timeAxis . vAtTime ( parseTime_PMILLIS ( json . minX ) ) ; var timeMax = timeAxis . vAtTime ( parseTime_PMILLIS ( json . maxX ) ) ; var ySize = json . sizeY ; var xSize = json . sizeX ; var array = new Float32Array ( xSize * ySize ) ; for ( var x = 0 ; x < xSize ; x ++ ) { for ( var y = 0 ; y < ySize ; y ++ ) { array [ y * xSize + x ] = json . data [ y ] [ x ] ; } } var createHeatmapPlotPane = function ( drawable , timeAxis , yAxis , model , row , ui , options ) : Pane { var axisColor = options . timelineFgColor ; var height = options . isMaximized ? null : 270 ; var colorAxis = new Axis1D ( - 0.7 , 0.3 ) ; colorAxis . limitsChanged . on ( drawable . redraw ) ; yAxis . setVRange ( 0 , 180 ) ; yAxis . limitsChanged . on ( drawable . redraw ) ; var rowAxis = new Axis2D ( timeAxis , yAxis ) ; var spacerPane = new Pane ( { updatePrefSize : fixedSize ( null , height ) } , false ) ; var yAxisPane = new Pane ( { updatePrefSize : fixedSize ( 40 , height ) } ) ; attachAxisMouseListeners1D ( yAxisPane , yAxis , true ) ; var colorAxisPane = new Pane ( { updatePrefSize : fixedSize ( 40 , height ) } ) ; attachAxisMouseListeners1D ( colorAxisPane , colorAxis , true ) ; var colorInsetPane = newInsetPane ( colorAxisPane , newInsets ( 10 , 10 , 10 , 10 ) , null , false ) ; colorInsetPane . addPainter ( newBlendingBackgroundPainter ( rgba ( 0 , 0 , 0 , 0.6 ) ) ) ; var data = { array : array , xSize : xSize , ySize : ySize , xMin : timeMin , xMax : timeMax , yMin : angleMin , yMax : angleMax } ; var colorGradient = reverseBone ; var colorScale = getGradientTexture ( colorGradient ) ; var plotPane = new Pane ( newColumnLayout ( ) , false ) ; plotPane . addPainter ( newHeatmapPainter ( rowAxis , colorAxis , data , colorScale , { blend : true } ) ) ; plotPane . addPainter ( newEdgeAxisPainter ( yAxis , Side . RIGHT , { showLabel : false , textColor : axisColor , tickColor : axisColor , tickSpacing : 34 , tickSize : 5 , font : '9px verdana,sans-serif' } ) ) ; colorAxisPane . addPainter ( newEdgeAxisPainter ( colorAxis , Side . RIGHT , { showLabel : false , textColor : axisColor , tickColor : axisColor , tickSpacing : 34 , tickSize : 10 , showBorder : true , gradientFill : colorGradient , font : '9px verdana,sans-serif' } ) ) ; plotPane . addPane ( yAxisPane , 0 ) ; plotPane . addPane ( spacerPane , 1 ) ; plotPane . addPane ( colorInsetPane , 2 ) ; return plotPane ; } ; ui . rowUi ( 'metsci.timelineExample.dynamicRow01' ) . paneFactory = createHeatmapPlotPane ; } ) ; var createHeatmapPlotPane = function ( drawable , timeAxis , yAxis , model , row , ui , options ) : Pane { var axisColor = options . timelineFgColor ; var height = options . isMaximized ? null : 270 ; var colorAxis = new Axis1D ( 0 , 30 ) ; colorAxis . limitsChanged . on ( drawable . redraw ) ; yAxis . setVRange ( - 400 , 400 ) ; yAxis . limitsChanged . on ( drawable . redraw ) ; var rowAxis = new Axis2D ( timeAxis , yAxis ) ; var spacerPane = new Pane ( { updatePrefSize : fixedSize ( null , height ) } , false ) ; var yAxisPane = new Pane ( { updatePrefSize : fixedSize ( 40 , height ) } ) ; attachAxisMouseListeners1D ( yAxisPane , yAxis , true ) ; var colorAxisPane = new Pane ( { updatePrefSize : fixedSize ( 40 , height ) } ) ; attachAxisMouseListeners1D ( colorAxisPane , colorAxis , true ) ; var colorInsetPane = newInsetPane ( colorAxisPane , newInsets ( 10 , 10 , 10 , 10 ) , null , false ) ; colorInsetPane . addPainter ( newBlendingBackgroundPainter ( rgba ( 0 , 0 , 0 , 0.6 ) ) ) ; var yMin = - 1000 ; var yMax = 1000 ; var timeMin = timeAxis . vAtTime ( parseTime_PMILLIS ( '2013-12-31T21:00:00Z' ) ) ; var timeMax = timeAxis . vAtTime ( parseTime_PMILLIS ( '2014-01-02T06:19:00Z' ) ) ; var xSize = 1000 ; var ySize = 300 ; var w = 2 * Math . PI / 60 ; var fr = 0 ; var array = new Float32Array ( xSize * ySize ) ; for ( var x = 0 ; x < xSize ; x ++ ) { for ( var y = 0 ; y < ySize ; y ++ ) { var x0 = 2 * Math . PI * x / xSize ; var x1 = 2 * Math . PI * y / ySize ; var value = 30 * Math . abs ( Math . sin ( x0 + w * fr ) ) * ( Math . sin ( x0 - w * fr ) * Math . sin ( 8 * x0 + w * fr ) * Math . cos ( - 8 * x1 - w * fr ) + Math . abs ( Math . sin ( 24 * x1 ) ) / 3 ) ; array [ y * xSize + x ] = value ; } } var data = { array : array , xSize : xSize , ySize : ySize , xMin : timeMin , xMax : timeMax , yMin : yMin , yMax : yMax } ; var colorGradient = jet ; var colorScale = getGradientTexture ( colorGradient ) ; var plotPane = new Pane ( newColumnLayout ( ) , false ) ; plotPane . addPainter ( newHeatmapPainter ( rowAxis , colorAxis , data , colorScale , { blend : true } ) ) ; plotPane . addPainter ( newEdgeAxisPainter ( yAxis , Side . RIGHT , { showLabel : false , textColor : axisColor , tickColor : axisColor , tickSpacing : 34 , tickSize : 5 , font : '9px verdana,sans-serif' } ) ) ; colorAxisPane . addPainter ( newEdgeAxisPainter ( colorAxis , Side . RIGHT , { showLabel : false , textColor : axisColor , tickColor : axisColor , tickSpacing : 34 , tickSize : 10 , showBorder : true , gradientFill : colorGradient , font : '9px verdana,sans-serif' } ) ) ; plotPane . addPane ( yAxisPane , 0 ) ; plotPane . addPane ( spacerPane , 1 ) ; plotPane . addPane ( colorInsetPane , 2 ) ; return plotPane ; } ; ui . rowUi ( 'metsci.timelineExample.dynamicRow02' ) . paneFactory = createHeatmapPlotPane ; $ . getJSON ( 'timelineData.json' , function ( newTimeline ) { model . merge ( newTimeline , timelineMergeNewBeforeOld ) ; var pane = ui . rowUi ( 'metsci.timelineExample.row03a' ) . getPane ( 'y-axis' ) ; var clickListener = function ( ev ) { console . log ( 'y-axis click: ' + ev . clickCount ) ; } ; pane . mouseDown . on ( clickListener ) ; } ) ; var reloadTimeline = function ( parentPane , oldTimelinePane , newOptions ) : TimelinePane { parentPane . removePane ( oldTimelinePane ) ; oldTimelinePane . dispose . fire ( ) ; var reloadedTimelinePane = newTimelinePane ( drawable , timeAxis , model , timelineOptions , oldTimelinePane . ui ) ; parentPane . addPane ( reloadedTimelinePane ) ; drawable . redraw ( ) ; return reloadedTimelinePane ; } ; } }