Out-HTML.ps1
function Out-HTML { <# .Synopsis Produces HTML output from the PowerShell pipeline. .Description Produces HTML output from the PowerShell pipeline, doing the best possible to obey the formatting rules in PowerShell. .Example Get-Process | Out-HTML .Link New-Webpage .Link Write-Link .Link New-Region #> [OutputType([string])] [CmdletBinding(DefaultParameterSetName='DefaultFormatter')] param( # The input object [Parameter(ValueFromPipeline=$true)] [PSObject] $InputObject, # If set, writes the response directly [switch] $WriteResponse, # If set, escapes the output [switch] $Escape, # The id of the table that will be created [string] $Id, # The vertical alignment of rows within the generated table. By default, aligns to top [ValidateSet('Baseline', 'Top', 'Bottom', 'Middle')] $VerticalAlignment = 'Top', # The table width, as a percentage [ValidateRange(1,100)] [Uint32] $TableWidth = 100, # The CSS class to apply to the table. [string] $CssClass, # A CSS Style [Hashtable] $Style, # If set, will enclose the output in a div with an itemscope and itemtype attribute [Parameter(ValueFromPipelineByPropertyName=$true)] [string[]]$ItemType, # If more than one view is available, this view will be used [string]$ViewName, # If set, will use the table sorter plugin [Switch] $UseTableSorter, # If set, will use the datatable plugin [Switch] $UseDataTable, # If set, will show the output as a pie graph [Parameter(Mandatory=$true,ParameterSetName='AsPieGraph')] [Switch] $AsPieGraph, # If set, will show the output as a bar graph [Parameter(Mandatory=$true,ParameterSetName='AsBarGraph')] [Switch] $AsBarGraph, # If set, the bar graph will be horizontal, not vertical [Parameter(ParameterSetName='AsBarGraph')] [Switch] $Horizontal, # The list of colors in the graph [Parameter(ParameterSetName='AsPieGraph')] [Parameter(ParameterSetName='AsBarGraph')] [string[]] $ColorList = @("#468966", "#FFF0A5", "#FF870C", "#CA0016", "#B0A5CF", "#2B85BA", "#11147D", "#EE56A9", "#ADDC6C", "#108F34"), # The width of the canvas for a graph [Parameter(ParameterSetName='AsPieGraph')] [Parameter(ParameterSetName='AsBarGraph')] [Double] $GraphWidth = 400, # The height of the canvas for a graph [Parameter(ParameterSetName='AsPieGraph')] [Parameter(ParameterSetName='AsBarGraph')] [Double] $GraphHeight = 400, # The header of a graph [Parameter(ParameterSetName='AsPieGraph')] [Parameter(ParameterSetName='AsBarGraph')] [string] $Header, # The text alignment of the header. By default, center [ValidateSet("Left", "Center", "Right")] [Parameter(ParameterSetName='AsPieGraph')] [Parameter(ParameterSetName='AsBarGraph')] [string] $HeaderAlignment = "Center", # The size of the header [ValidateRange(1,6)] [Parameter(ParameterSetName='AsPieGraph')] [Parameter(ParameterSetName='AsBarGraph')] [Uint32] $HeaderSize = 3, # If set, no legend will be displayed [Parameter(ParameterSetName='AsPieGraph')] [Parameter(ParameterSetName='AsBarGraph')] [Switch] $HideLegend ) begin { $tablesForTypeNames = @{} $tableCalculatedProperties = @{} if (-not $Script:CachedformatData) { $Script:CachedformatData = @{} } $stopLookingFor = @{} $CachedControls = @{} $loadedViewFiles= @{} $htmlOut = New-Object Text.StringBuilder $typeNamesEncountered = @() if (-not $script:LoadedFormatFiles) { $script:loadedFormatFiles = @(dir $psHome -Filter *.format.ps1xml | Select-Object -ExpandProperty Fullname) + @(Get-Module | Select-Object -ExpandProperty ExportedformatFiles) $script:loadedViews = $loadedFormatFiles | Select-Xml -Path {$_ } "//View" } if ($useTableSorter) { if ($CssClass) { $CssClass+="tableSorterTable" } else { $CssClass ="tableSorterTable" } } if ($useDataTable) { if ($CssClass) { $CssClass+="aDataTable" } else { $CssClass ="aDataTable" } } $userandomSalt = $false $graphData = $null $graphItemOrder = @() if ($AsPieGraph) { $userandomSalt = $true $graphData= @{} } if ($AsBarGraph) { $userandomSalt = $true $graphData = @{} } } process { # In case nulls come in, exit politely if (-not $InputObject ) { return } $randomSalt = if ($userandomSalt) { "_$(Get-Random)" } else { "" } $classChunk = if ($cssClass) { "class='$($cssClass -join ' ')'" } else { "" } $cssStyleChunk = if ($psBoundParameters.Style) { if ($AsPieGraph -or $AsBarGraph) { if (-not $style['width']) { $style['width'] = "${GraphWidth}px" } else { $GraphWidth = $style['Width'] } if (-not $style['height']) { $style['height'] = "$($GraphHeight + 100)px" } else { $GraphHeight = $style['Height'] } } "style='" +(Write-CSS -Style $style -OutputAttribute) + "'" } else { if ($AsPieGraph -or $AsBarGraph) { "style='" +(Write-CSS -Style @{"width"="${GraphWidth}px";"height"="$($GraphHeight + 50)px"} -OutputAttribute) + "'" } else { "style='width:100%'" } } if ($inputObject -is [string]) { # Strings are often simply passed thru, but could potentially be escaped. $trimmedString = $inputObject.TrimStart([Environment]::NewLine).TrimEnd([Environment]::NewLine).TrimStart().TrimEnd() # If the string looks @ all like markup or HTML, pass it thru if ($graphData) { if (-not $graphData.$trimmedString) { $graphData.$trimmedString = 0 } $graphData.$trimmedString++ if ($graphItemOrder -notcontains $trimmedString) { $graphItemOrder += $trimmedString } } else { if (($trimmedString -like "*<*") -and ($trimmedString -like "*>*") -and ($trimmedString -notlike "*<?xml*")) { if ($escape) { $null = $htmlOut.Append(" $([Web.HttpUtility]::HtmlEncode($inputObject).Replace([Environment]::NewLine, '<BR/>').Replace('`n', '<BR/>').Replace(' ', ' ')) ") } else { $null = $htmlOut.Append(" $inputObject ") } } else { # Otherwise, include it within a <pre> tag $null= $htmlOut.Append(" $([Web.HttpUtility]::HtmlEncode($inputObject)) ") } } } elseif ([Double], [int], [uint32], [long], [byte] -contains $inputObject.GetType()) { if ($graphData) { if (-not $graphData.$inputObject) { $graphData.$inputObject = 0 } $graphData.$inputObject += $graphData.$inputObject if ($graphItemOrder -notcontains $inputObject) { $graphItemOrder += $inputObject } } else { # If it's a number, simply print it out $null= $htmlOut.Append(" <span class='Number' style='font-size:2em'> $inputObject </span> ") } } elseif ([DateTime] -eq $inputObject.GetType()) { # If it's a date, out Out-String to print the long format if ($graphData) { if (-not $graphData.$inputObject) { $graphData.$inputObject = 0 } $graphData.$inputObject++ if ($graphItemOrder -notcontains $inputObject) { $graphItemOrder += $inputObject } } else { $null= $htmlOut.Append(" <span class='DateTime'> $($inputObject | Out-String) </span> ") } } elseif (($inputObject -is [Hashtable]) -or ($inputObject -is [Collections.IDictionary])) { $null = $psBoundParameters.Remove('InputObject') $inputObjecttypeName = "" $inputObjectcopy = @{} + $inputObject if ($inputObjectcopy.PSTypeName) { $inputObjecttypeName = $inputObject.PSTypeName $inputObjectcopy.Remove('PSTypeName') } foreach ($kv in @($inputObjectcopy.GetEnumerator())) { if ($kv.Value -is [Hashtable]) { $inputObjectcopy[$kv.Key] = Out-HTML -InputObject $kv.Value } } if ($inputObjectCopy) { New-Object PSObject -Property $inputObjectcopy | ForEach-Object { $_.pstypenames.clear() foreach ($inTypeName in $inputObjectTypeName) { if (-not $inTypeName) {continue } $null = $_.pstypenames.add($inTypeName) } if (-not $_.pstypenames) { $_.pstypenames.add('PropertyBag') } $psBoundparameters.ItemType = $inputObjectTypeName $_ } | Out-HTML @psboundParameters } } else { $matchingTypeName = $null #region Match TypeName to Formatter foreach ($typeName in $inputObject.psObject.typenames) { # Skip out of $typeName = $typename.TrimStart("Deserialized.") if ($stopLookingFor[$typeName]) { continue } if ($Script:CachedformatData[$typeName] ) { $matchingTypeName = $typename break } if (-not $Script:CachedformatData[$typeName] -and -not $stopLookingFor[$TypeName]) { $Script:CachedformatData[$typeName] = if ([IO.File]::Exists("$pwd\Presenters\$typeName")) { if ($loadedViewFiles[$typeName]) { $loadedViewFiles[$typeName] = [IO.File]::ReadAllText( $ExecutionContext.SessionState.Path.GetResolvedProviderPathFromPSPath(".\Presenters\$typeName")) } else { $loadedViewFiles[$typeName] } } else { Get-FormatData -TypeName $typeName -ErrorAction SilentlyContinue } if (-not $Script:CachedformatData[$TypeName]) { # This covers custom action $Script:CachedformatData[$typeName] = foreach ($view in $loadedViews) { if ($view.Node.ViewselectedBy.TypeName -eq $typeNAme) { if ($ViewName -and $view.Node.Name -eq $viewNAme) { $view.Node break } else { $view.Node break } } } if ($Script:CachedformatData[$typeName]) { # Custom Formatting or SelectionSet if ($Script:CachedformatData[$typeName]) { } $matchingTypeName = $typeName } else { # At this point, we're reasonably certain that no formatter exists, so # Make sure we stop looking for the typename, or else this expensive check is repeated for each item if (-not $Script:CachedformatData[$typeName]) { $stopLookingFor[$typeName] = $true } } } else { $matchingTypeName = $typeName break } } } $TypeName = $MatchingtypeName #endregion Match TypeName to Formatter if ($GraphData) { # Formatted type doesn't really matter when we're graphing, so skip all the logic related to it foreach ($pr in $InputObject.PSObject.Properties) { if (-not $graphData.($pr.Name)) { $graphData.($pr.Name) = 0 } if ($pr.Value) { if ([Double], [int], [uint32], [long], [byte] -contains $pr.Value.GetType()) { $graphData.($pr.Name)+=$pr.Value } else { $graphData.($pr.Name)++ } } if ($graphItemOrder -notcontains $pr.Name) { $graphItemOrder += $pr.Name } } } elseif ($matchingTypeName) { $formatData = $Script:CachedformatData[$typeName] $cssSafeTypeName =$typename.Replace('.','').Replace('#','') if ($Script:CachedformatData[$typeName] -is [string]) { # If it's a string, just set $_ and expand the string, which allows subexpressions inside of HTML $_ = $inputObject foreach ($prop in $inputObject.psobject.properties) { Set-Variable $prop.Name -Value $prop.Value -ErrorAction SilentlyContinue } $ExecutionContext.SessionState.InvokeCommand.ExpandString($Script:CachedformatData[$typeName]) } elseif ($Script:CachedformatData[$typeName] -is [Xml.XmlElement]) { # SelectionSet or Custom Formatting Action $frame = $Script:CachedformatData[$typeName].CustomControl.customentries.customentry.customitem.frame foreach ($frameItem in $frame) { $item =$frameItem.customItem foreach ($expressionItem in $item) { if (-not $expressionItem) { continue } $expressionItem | Select-Xml "ExpressionBinding|NewLine" | ForEach-Object -Begin { if ($itemType) { #$null = $htmlOut.Append("<div itemscope='' itemtype='$($itemType -join "','")' class='ui-widget-content'>") } } { if ($_.Node.Name -eq 'ExpressionBinding') { $finalExpr =($_.Node.SelectNodes("ScriptBlock") | ForEach-Object { $_."#text" }) -ireplace "Write-Host", "Write-Host -AsHtml" -ireplace "Microsoft.PowerShell.Utility\Write-Host", "Write-Host" $_ = $inputObject $null = $htmlOut.Append("$(Invoke-Expression $finalExpr)") } elseif ($_.Node.Name -eq 'Newline') { $null = $htmlOut.Append("<br/>") } } -End { if ($itemType) { #$null = $htmlOut.Append("</div>") } }| Where-Object { $_.Node.Name -eq 'ExpressionBinding' } if (-not $expressionBinding.firstChild.ItemSelectionCondition) { } } } $null = $null # Lets see what to do here } else { if (-not $CachedControls[$typeName]) { $control = foreach ($_ in $formatData.FormatViewDefinition) { if (-not $_) { continue } $result = foreach ($ctrl in $_.Control) { if ($ctrl.Headers) { $ctrl break } } if ($result) { $result break } } $CachedControls[$typeName]= $control if (-not $cachedControls[$TypeName]) { $control = foreach ($_ in $formatData.CustomControl) { if (-not $_) { continue } } $CachedControls[$typeName]= $control } } $control = $CachedControls[$typeName] if (-not ($tablesForTypeNames[$typeName])) { $tableCalculatedProperties[$typeName] = @{} if (-not $psBoundParameters.id) { $id = "TableFor$($TypeName.Replace('/', '_Slash_').Replace('.', "_").Replace(" ", '_'))$(Get-Random)" } else { $id = $psBoundParameters.id } $tableHeader = New-Object Text.StringBuilder $null = $tableHeader.Append(" $(if ($useTableSorter) { '<script> $(function() { $(".tableSorterTable").tablesorter(); }) </script>' }) $(if ($useDataTable) { '<script> $(function() { $(".aDataTable").dataTable(); }) </script>' }) <table id='${id}${randomSalt}' $classChunk $cssstyleChunk> <thead> <tr>") $labels = @() $headerCount = $control.Headers.Count $columns = @($control.Rows[0].Columns) for ($i=0; $i-lt$headerCount;$i++) { $header = $control.Headers[$i] $label = $header.Label if (-not $label) { $label = $columns[$i].DisplayEntry.Value } if ($label) { if ($columns[$i].DisplayEntry.ValueType -eq 'Property') { $prop = $columns[$i].DisplayEntry.Value $tableCalculatedProperties[$label] = [ScriptBlock]::Create("`$inputObject.'$prop'") } elseif ($columns[$i].DisplayEntry.ValueType -eq 'ScriptBlock') { $tableCalculatedProperties[$label] = [ScriptBlock]::Create($columns[$i].DisplayEntry.Value) } $labels+=$label } $null = $tableHeader.Append(" <th style='font-size:1.1em;text-align:left;line-height:133%'>$([Security.SecurityElement]::Escape($label))<hr/></th>") } $null = $tableHeader.Append(" </tr> </thead> <tbody> ") $tablesForTypeNames[$typeName] = $tableHeader $typeNamesEncountered += $typeName } $currentTable = $tablesForTypeNames[$typeName] # Add a row $null = $currentTable.Append(" <tr itemscope='' itemtype='$($typeName)'>") foreach ($label in $labels) { $value = "&nsbp;" if ($tableCalculatedProperties[$label]) { $_ = $inputObject $value = . $tableCalculatedProperties[$label] } $value = "$($value -join ([Environment]::NewLine))".Replace([Environment]::NewLine, '<BR/> ') if ($value -match '^http[s]*://') { $value = Write-Link -Url $value -Caption $value } $null = $currentTable.Append(" <td style='vertical-align:$verticalAlignment' itemprop='$([Security.SecurityElement]::Escape($label))'>$($value.Replace('&', '&'))</td>") } $null = $currentTable.Append(" </tr>") } } else { # Default Formatting rules $labels = @(foreach ($pr in $inputObject.psObject.properties) { $pr.Name }) if (-not $labels) { return } [int]$percentPerColumn = 100 / $labels.Count if ($inputObject.PSObject.Properties.Count -gt 4) { $null = $htmlOut.Append(" <div class='${cssSafeTypeName}Item'> ") foreach ($prop in $inputObject.psObject.properties) { $null = $htmlOut.Append(" <p class='${cssSafeTypeName}PropertyName'>$($prop.Name)</p> <blockquote> <pre class='${cssSafeTypeName}PropertyValue'>$($prop.Value)</pre> </blockquote> ") } $null = $htmlOut.Append(" </div> <hr class='${cssSafeTypeName}Separator' /> ") } else { $widthPercentage = 100 / $labels.Count $typeName = $inputObject.pstypenames[0] if (-not ($tablesForTypeNames[$typeName])) { $tableCalculatedProperties[$typeName] = @{} if (-not $psBoundParameters.id) { $id = "TableFor$($TypeName.Replace('/', '_Slash_').Replace('.', "_").Replace(" ", '_'))$(Get-Random)" } else { $id = $psBoundParameters.id } $tableHeader = New-Object Text.StringBuilder $null = $tableHeader.Append(" $(if ($useTableSorter) { '<script> $(function() { $(".tableSorterTable").tablesorter(); }) </script>' }) $(if ($useDataTable) { '<script> $(function() { $(".aDataTable").dataTable(); }) </script>' }) <table id='${id}${randomSalt}' $cssStyleChunk $classChunk > <thead> <tr>") foreach ($label in $labels) { $null = $tableHeader.Append(" <th style='font-size:1.1em;text-align:left;line-height:133%;width:${widthPercentage}%'>$([Security.SecurityElement]::Escape($label))<hr/></th>") } $null = $tableHeader.Append(" </tr> </thead> <tbody>") $tablesForTypeNames[$typeName] = $tableHeader $typeNamesEncountered += $typeName } $currentTable = $tablesForTypeNames[$typeName] # Add a row $null = $currentTable.Append(" <tr itemscope='' itemtype='$($typeName)'>") foreach ($label in $labels) { $value = "&nsbp;" $value = $inputObject.$label $value = "$($value -join ([Environment]::NewLine))".Replace([Environment]::NewLine, '<BR/> ') if ($value -match '^http[s]*://') { $value = Write-Link $value } $null = $currentTable.Append(" <td style='vertical-align:$verticalAlignment' itemprop='$([Security.SecurityElement]::Escape($label))'>$($value.Replace('&', '&'))</td>") } $null = $currentTable.Append(" </tr>") } } } } end { $htmlOut = "$htmlOut" $htmlOut += if ($tablesForTypeNames.Count) { foreach ($table in $typeNamesEncountered) { if ($AsBarGraph) { $null = $tablesForTypeNames[$table].Append(@" </tbody></table> <div id='${id}_Holder_${RandomSalt}'> </div> <div style='clear:both'> </div> <script> `$(function () { // Grab the data colors = ["$($ColorList -join '","')"] var data = [], labels = []; `$("#${Id}${RandomSalt} thead tr th").each( function () { labels.push(`$(this).text()); }); `$("#${Id}${RandomSalt} tbody tr td").each( function () { data.push( parseInt( `$(this).text(), 10) ); }); `$("#${Id}${RandomSalt}").hide(); chartHtml = '<table valign="bottom"><tr><td valign="bottom">' valueTotal = 0 for (i =0; i< labels.length;i++) { chartHtml += ("<div id='${RandomSalt}_" + i + "' style='min-width:50px;float:left;ver' > <div id='${RandomSalt}_" + i + "_Rect' style='height:1px;background-color:" + colors[i] + "'> </div><br/><div class='chartLabel'>"+ labels[i] + '<br/>(' + data[i] + ")</div></div>"); valueTotal += data[i]; chartHtml+= '</td>' if (i < (labels.length - 1)) { chartHtml+= '<td valign="bottom">' } } chartHtml += '</tr></table>' `$(${id}_Holder_${RandomSalt}).html(chartHtml); for (i =0; i< labels.length;i++) { newRelativeHeight = (data[i] / valueTotal) * 200; `$(("#${RandomSalt}_" + i + "_Rect")).animate({ height:newRelativeHeight }, 500); } }); </script> "@) } else { $null = $tablesForTypeNames[$table].Append(" </tbody></table>") } if ($escape) { [Web.HttpUtility]::HtmlEncode($tablesForTypeNames[$table].ToString()) } else { $tablesForTypeNames[$table].ToString() } } } if ($itemType) { $htmlout = "<div itemscope='' itemtype='$($itemType -join ' ')'> $htmlOut </div>" } if ($graphData) { $legendHtml = "" if (-not $HideLegend) { $c =0 $legendHtml = foreach ($graphItem in $graphItemOrder) { $val = $graphData[$graphItem] $lang = Get-Culture if ($request -and $request["Accept-Language"]) { $matchingLang = [Globalization.CultureInfo]::GetCultures("All") | Where-Object {$_.Name -eq $request["Accept-Language"]} if ($matchingLang) { $lang = $matchingLang } } $formattedVal = if ($AsCurrency) { $v = $val.ToString("c", $lang) if ($v -like "*$($lang.NumberFormat.CurrencyDecimalSeparator)00") { $v.Substring(0, $v.Length - 3) } else { $v } } else { $v = $val.ToString("n", $lang) if ($v -like "*$($lang.NumberFormat.NumberDecimalSeparator)00") { $v.Substring(0, $v.Length - 3) } else { $v } } " <div style='margin-top:5px'> <div style='background-color:$($colorList[$c]);width:20px;height:20px;content:"";'> <div style='font-weight:bold;height:20px;vertical-align:middle;display:inline;margin-left:25px;position:absolute'> $graphItem $(if (-not $HideValue) { "($formattedVal)" }) </div> </div> </div> " $C++ } } if ($AsPieGraph) { $pieStyle = " #Graph$RandomSalt .pie { position:absolute; width:$($GraphWidth / 2)px; height:$($GraphHeight)px; overflow:hidden; left:$($graphWidth * .75)px; -moz-transform-origin:left center; -ms-transform-origin:left center; -o-transform-origin:left center; -webkit-transform-origin:left center; transform-origin:left center; } #Graph$RandomSalt .pie.big { position:absolute; width:${GraphWidth}px; height:${GraphHeight}px; left:$($GraphWidth * .25)px; -moz-transform-origin:center center; -ms-transform-origin:center center; -o-transform-origin:center center; -webkit-transform-origin:center center; transform-origin:center center; } #Graph$RandomSalt .pie:BEFORE { content:''; position:absolute; width:$($GraphWidth / 2)px; height:$($GraphHeight)px; left:-$($GraphWidth / 2)px; border-radius:$($GraphWidth / 2)px 0 0 $($GraphWidth / 2)px; -moz-transform-origin:right center; -ms-transform-origin:right center; -o-transform-origin:right center; -webkit-transform-origin:right center; transform-origin:right center; } #Graph$RandomSalt .pie.big:BEFORE { left:0px; } #Graph$RandomSalt .pie.big:AFTER { content:''; position:absolute; width:$($GraphWidth / 2)px; height:${GraphHeight}px; left:$($GraphWidth / 2)px; border-radius:0 $($GraphWidth / 2)px $($GraphWidth / 2)px 0; } $( $c = 0 foreach ($color in $ColorList) { $c++ @" #Graph$RandomSalt .pie:nth-of-type($c):BEFORE, #Graph$RandomSalt .pie:nth-of-type($c):AFTER { background-color:$color; } "@ }) $( $dataStart = 0 $totalSliced = 0 $totalSliced = $graphData.Values | Measure-Object -Sum | Select-Object -ExpandProperty Sum $dc = 0 $pieHtml = '' foreach ($graphItem in $graphItemOrder) { $val = $graphData[$graphItem] $percentOfTotal = $val / $totalSliced $percentInDegrees = 360 * $percentOfTotal $dataEnd = $dataStart + [int]$percentInDegrees $pieHtml += if ($percentInDegrees -lt 180) { " <div class='pie' data-start='$DataStart' data-value='$([int]$percentInDegrees)'></div> " } else { " <div class='pie big' data-start='$DataStart' data-value='$([int]$percentInDegrees)'></div> " } @" #Graph$RandomSalt .pie[data-start="$dataStart"] { -moz-transform: rotate(${DataStart}deg); /* Firefox */ -ms-transform: rotate(${DataStart}deg); /* IE */ -webkit-transform: rotate(${DataStart}deg); /* Safari and Chrome */ -o-transform: rotate(${DataStart}deg); /* Opera */ transform:rotate(${DataStart}deg); filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=${DataStart}); } "@ if ($dc -lt ($graphData.Count - 1)) { @" #Graph$RandomSalt .pie[data-value="$([int]$percentInDegrees)"]:BEFORE { -moz-transform: rotate($([int]($percentInDegrees + 1))deg); /* Firefox */ -ms-transform: rotate($([int]($percentInDegrees + 1))deg); /* IE */ -webkit-transform: rotate($([int]($percentInDegrees + 1))deg); /* Safari and Chrome */ -o-transform: rotate($([int]($percentInDegrees + 1))deg); /* Opera */ transform:rotate($([int]($percentInDegrees + 1))deg); filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=$([int]($percentInDegrees + 1))); } "@ } else { @" #Graph$RandomSalt .pie[data-value="$([int]$percentInDegrees)"]:BEFORE { -moz-transform: rotate($([int]($percentInDegrees))deg); /* Firefox */ -ms-transform: rotate($([int]($percentInDegrees))deg); /* IE */ -webkit-transform: rotate($([int]($percentInDegrees))deg); /* Safari and Chrome */ -o-transform: rotate($([int]($percentInDegrees))deg); /* Opera */ transform:rotate($([int]($percentInDegrees))deg); filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=$([int]($percentInDegrees))); } "@ } $dc++ $dataStart = $dataEnd } ) " } elseif ($asBarGraph) { $pieStyle = @" $( $dataStart = 0 $totalSliced = 0 $totalSliced = $graphData.Values | Measure-Object -Maximum $totalMax = $totalSliced | Select-Object -ExpandProperty Maximum $totalSliced = $totalSliced | Select-Object -ExpandProperty Sum $dc = 0 $pieHtml = '' foreach ($graphItem in $graphItemOrder) { $val = $graphData[$graphItem] $percentOfTotal = $val / ($totalMax * 1.1) if (-not $Horizontal) { $percentHeight = $GraphHeight * $percentOfTotal $pieHtml += " <div style='float:left;position:relative;vertical-align:bottom;bottom:0;width:$($graphWidth * .66 / $graphData.Count)px;height:$([Math]::round($percentHeight))px;margin-left:$($graphWidth * .33/ $graphData.Count)px'> <div class='barItemTop' style='height:$($graphHeight * (1-$percentOfTotal))px;'> </div> <div class='barChartItem' data-value='$val' data-percent='$percentOfTotal' style='width:$([Math]::Round($graphWidth * .66 / $graphData.Count))px;height:$($percentHeight)px;background-color:$($colorList[$dc])'> </div> </div> " } else { $percentWidth = $GraphWidth * $percentOfTotal $pieHtml += " <div style='width:$($percentWidth)px;height:$($GraphHeight * .66 / $graphData.Count)px;margin-bottom:$($graphHeight * .33/ $graphData.Count)px;background-color:$($colorList[$dc])'> </div> " } $dc++ $dataStart = $dataEnd } ) "@ } $htmlOut = if ($graphData.Count) { $cssStyleChunk = if ($psBoundParameters.Style) { if ($AsPieGraph -or $AsBarGraph) { $style['width'] = "${GraphWidth}px" $style['height'] = "$($GraphHeight + $graphData.Count * 55)px" } "style='" +(Write-CSS -Style $style -OutputAttribute) + "'" } else { if ($AsPieGraph -or $AsBarGraph) { "style='" +(Write-CSS -Style @{"width"="${GraphWidth}px";"height"="$($GraphHeight + $graphData.Count * 55)px"} -OutputAttribute) + "'" } else { "style='width:100%'" } } " <div id='Graph$RandomSalt' $cssStyleChunk> $(if ($Header) { "<h$HeaderSize style='text-align:$($headerAlignment.ToLower());width:${graphWidth}px'>$($header)</h$HeaderSize>" }) <div style='width:$GraphWidth;height;$GraphHeight;position:relative'> $(if ($pieStyle) { "<style> $PieStyle </style> "}) $pieHtml </div> <div class='GraphLegend' style='clear:both;$(if ($AsPieGraph) { "position:relative;top:$($GraphHeight)px" })'> $legendHtml </div> </div> " } $null = $null } if ($WriteResponse -and $Response.Write) { $Response.Write("$htmlOut") } else { $htmlOut } } } |