import powerbi from 'powerbi-visuals-api' ; import IVisualHost = powerbi . extensibility . visual . IVisualHost ; import ISelectionManager = powerbi . extensibility . ISelectionManager ; import * as d3Select from 'd3-selection' ; import * as OverlayScrollbars from 'overlayscrollbars' ; var pretty = require ( 'pretty' ) ; import { VisualConstants } from './VisualConstants' ; import { StylesheetSettings , VisualSettings } from './VisualSettings' ; export namespace DomainUtils { /**
     * Use to determine if we should include stylesheet logic, based on whether it has been supplied or not.
     */ export const shouldUseStylesheet = ( stylesheet ) => stylesheet . stylesheet ? true : false ; /**
     * Resolve how styling should be applied, based on supplied properties. Basically, if user has supplied
     * their own stylesheet via properties, we will defer to this rather than the standard content formatting
     * ones.
     */ export const resolveStyling = ( styleSheetContainer , bodyContainer , settings ) => { const useSS = shouldUseStylesheet ( settings . stylesheet ) , bodyProps = settings . contentFormatting ; styleSheetContainer . text ( ( useSS && settings . stylesheet . stylesheet ) || '' ) ; resolveUserSelect ( bodyProps . userSelect , bodyContainer ) ; bodyContainer . style ( 'font-family' , resolveBodyStyle ( useSS , bodyProps . fontFamily ) ) . style ( 'font-size' , resolveBodyStyle ( useSS , `${ bodyProps . fontSize }pt` ) ) . style ( 'color' , resolveBodyStyle ( useSS , bodyProps . fontColour ) ) . style ( 'text-align' , resolveBodyStyle ( useSS , bodyProps . align ) ) ; } ; /**
     * For the supplied stylesheet container, settings and body container (could be standard content, or the
     * "no data" message container), ensure that the content is resolved, and the correct element (readonly
     * textarea) is added to the DOM, as well as caretaking any existing elements.
     */ export const resolveForRawHtml = ( styleSheetContainer , contentContainer , settings ) => { if ( settings . contentFormatting . showRawHtml ) { const output = getRawHtml ( styleSheetContainer , contentContainer , settings . stylesheet ) ; contentContainer . selectAll ( '*' ) . remove ( ) ; contentContainer . append ( 'textarea' ) . attr ( 'id' , VisualConstants . dom . rawOutputIdSelector ) . attr ( 'readonly' , true ) . text ( output ) ; } } ; param host param container param allowDelegation export function resolveHyperlinkHandling ( host , container , allowDelegation ? ) { container . selectAll ( 'a' ) . on ( 'click' , ( d , i , e ) => { d3Select . event . preventDefault ( ) ; allowDelegation && host . launchUrl ( d3Select . select ( e [ i ] ) . attr ( 'href' ) ) ; } ) ; } param dataElements export function resolveHtmlGroupElement ( dataElements ) { dataElements . selectAll ( '*' ) . remove ( ) ; dataElements . append ( 'div' ) . html ( d => d ) ; } param element export function resolveScrollableContent ( element ) { OverlayScrollbars ( element , { scrollbars : { clickScrolling : true } } ) ; } param container param selectionManager export function resolveContextMenu ( container , selectionManager ) { container . on ( 'contextmenu' , ( ) => { const mouseEvent = < MouseEvent > d3Select . event ; selectionManager . showContextMenu ( { } , { x : mouseEvent . x , y : mouseEvent . y } ) ; mouseEvent . preventDefault ( ) ; } ) ; } param container param data export function bindVisualDataToDom ( container , data ) { return container . selectAll ( `.${ VisualConstants . dom . entryClassSelector }` ) . data ( data ) . join ( enter => enter . append ( 'div' ) . classed ( VisualConstants . dom . entryClassSelector , true ) ) ; } /**
     * For the supplied stylesheet container, settings and body container (could be standard content, or the
     * "no data" message container), get raw HTML and pretty print it.
     */ const getRawHtml = ( styleSheetContainer , container , stylesheet ) => pretty ( `${ ( ( shouldUseStylesheet ( stylesheet ) && stylesheet . stylesheet ) || '' ) && styleSheetContainer . node ( ) . outerHTML } ${ container . node ( ) . outerHTML }` ) ; /**
     * Ensure that inline CSS is set correctly, based on whether user has assigned their own stylesheet,
     * or fall back to the standard content formatting properties if not.
     */ const resolveBodyStyle = ( useSS , prop ) => ( ! useSS && prop ) || null ; /**
     * Set the `user-select` CSS property based on user preference.
     */ const resolveUserSelect = ( enabled , bodyContainer ) => { const value = ( enabled && 'text' ) || 'none' ; bodyContainer . style ( 'user-select' , value ) . style ( '-moz-user-select' , value ) . style ( '-webkit-user-select' , value ) . style ( '-ms-user-select' , value ) ; } ; } export default DomainUtils ;