@websy/websy-designs 1.4.33 → 1.4.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6570,6 +6570,10 @@ class WebsyTable3 {
6570
6570
  headEl.style.width = 'initial'
6571
6571
  bodyEl.style.width = 'initial'
6572
6572
  this.sizes.bodyHeight = this.sizes.table.height - (this.sizes.header.height + this.sizes.total.height)
6573
+ if (this.options.maxHeight) {
6574
+ let requiredHeight = ((this.totalRowCount || 9) + 1) * this.sizes.cellHeight
6575
+ this.sizes.bodyHeight = Math.min(requiredHeight, this.options.maxHeight - (this.sizes.header.height + this.sizes.total.height))
6576
+ }
6573
6577
  this.sizes.rowsToRender = Math.ceil(this.sizes.bodyHeight / this.sizes.cellHeight)
6574
6578
  this.sizes.rowsToRenderPrecise = this.sizes.bodyHeight / this.sizes.cellHeight
6575
6579
  this.startRow = 0
@@ -6756,7 +6760,13 @@ class WebsyTable3 {
6756
6760
  }
6757
6761
  let bodyEl = document.getElementById(`${this.elementId}_tableBody`)
6758
6762
  // bodyEl.innerHTML = this.buildBodyHtml(data, true)
6759
- bodyEl.style.height = `calc(100% - ${this.sizes.header.height}px - ${this.sizes.total.height}px)`
6763
+ // if (this.options.maxHeight) {
6764
+ // bodyEl.style.height = `${this.options.maxHeight - this.sizes.header.height - this.sizes.total.height}px`
6765
+ // }
6766
+ // else {
6767
+ // bodyEl.style.height = `calc(100% - ${this.sizes.header.height}px - ${this.sizes.total.height}px)`
6768
+ // }
6769
+ bodyEl.style.height = `${this.sizes.bodyHeight}px`
6760
6770
  if (this.options.virtualScroll === true) {
6761
6771
  // set the scroll element positions
6762
6772
  let vScrollEl = document.getElementById(`${this.elementId}_vScrollContainer`)
@@ -6954,7 +6964,9 @@ class WebsyChart {
6954
6964
  showTooltip: true,
6955
6965
  showLegend: false,
6956
6966
  legendPosition: 'bottom',
6957
- tooltipWidth: 200
6967
+ tooltipWidth: 200,
6968
+ brushHeight: 50,
6969
+ minBandWidth: 30
6958
6970
  }
6959
6971
  this.elementId = elementId
6960
6972
  this.options = Object.assign({}, DEFAULTS, options)
@@ -6963,15 +6975,21 @@ class WebsyChart {
6963
6975
  this.topAxis = null
6964
6976
  this.bottomAxis = null
6965
6977
  this.renderedKeys = {}
6978
+ this.brushedDomain = []
6979
+ this.brushBarsInitialized = {}
6966
6980
  if (!elementId) {
6967
6981
  console.log('No element Id provided for Websy Chart')
6968
6982
  return
6969
6983
  }
6970
- this.invertOverride = (input, input2) => {
6971
- let xAxis = 'bottomAxis'
6984
+ this.invertOverride = (input, input2, forBrush = false) => {
6985
+ let xAxis = 'bottom'
6972
6986
  if (this.options.orientation === 'horizontal') {
6973
- xAxis = 'leftAxis'
6987
+ xAxis = 'left'
6988
+ }
6989
+ if (forBrush === true) {
6990
+ xAxis += 'Brush'
6974
6991
  }
6992
+ xAxis += 'Axis'
6975
6993
  let width = this[xAxis].step()
6976
6994
  let output
6977
6995
  let domain = [...this[xAxis].domain()]
@@ -6987,6 +7005,65 @@ class WebsyChart {
6987
7005
  }
6988
7006
  }
6989
7007
  return output
7008
+ }
7009
+ let that = this
7010
+ this.brushed = function (event) {
7011
+ console.log('brushing', event)
7012
+ that.brushedDomain = []
7013
+ let xAxis = 'bottom'
7014
+ let xAxisCaps = 'Bottom'
7015
+ if (that.options.orientation === 'horizontal') {
7016
+ xAxis = 'left'
7017
+ xAxisCaps = 'Left'
7018
+ }
7019
+ if (!that[`${xAxis}Axis`].invert) {
7020
+ that[`${xAxis}Axis`].invert = that.invertOverride
7021
+ }
7022
+ let s = event.selection || that[`${xAxis}Axis`].range()
7023
+ if (!event.selection || event.selection.length === 0) {
7024
+ that.brushLayer
7025
+ .select('.brush')
7026
+ .call(that.brush)
7027
+ .call(that.brush.move, s)
7028
+ return
7029
+ }
7030
+ if (that.options.data[xAxis].scale && that.options.data[xAxis].scale === 'Time') {
7031
+ that.brushedDomain = s.map(that[`${xAxis}BrushAxis`].invert, that[[`${xAxis}Axis`]])
7032
+ }
7033
+ else {
7034
+ let startEndOrdinal = s.map((a, b) => that.bottomAxis.invert(a, b, true), that.bottomBrushAxis)
7035
+ if (
7036
+ startEndOrdinal &&
7037
+ startEndOrdinal.length === 2 &&
7038
+ typeof startEndOrdinal[0] !== 'undefined' &&
7039
+ typeof startEndOrdinal[1] !== 'undefined'
7040
+ ) {
7041
+ let domain = []
7042
+ let domainValues = [...that[`${xAxis}BrushAxis`].domain()]
7043
+ for (let i = startEndOrdinal[0]; i < startEndOrdinal[1] + 1; i++) {
7044
+ // domain.push(that.xRange[i])
7045
+ that.brushedDomain.push(domainValues[i])
7046
+ }
7047
+ }
7048
+ }
7049
+ if (that.brushedDomain.length > 0) {
7050
+ that[`${xAxis}Axis`].domain(that.brushedDomain)
7051
+ that[`${xAxis}AxisLayer`].call(
7052
+ d3[`axis${xAxisCaps}`](that[`${xAxis}Axis`])
7053
+ )
7054
+ }
7055
+ if (that.leftAxis && that.bottomAxis) {
7056
+ that.renderComponents()
7057
+ if (that.options.orientation === 'vertical') {
7058
+ // that.bottomAxisLayer.call(that.bAxisFunc)
7059
+ if (that.options.data.bottom.rotate) {
7060
+ that.bottomAxisLayer.selectAll('text')
7061
+ .attr('transform', `rotate(${((that.options.data.bottom && that.options.data.bottom.rotate) || 0)})`)
7062
+ .style('text-anchor', `${((that.options.data.bottom && that.options.data.bottom.rotate) || 0) === 0 ? 'middle' : 'end'}`)
7063
+ .style('transform-origin', ((that.options.data.bottom && that.options.data.bottom.rotate) || 0) === 0 ? '0 0' : `0 ${((that.options.data.bottom && that.options.data.bottom.fontSize) || that.options.fontSize)}px`)
7064
+ }
7065
+ }
7066
+ }
6990
7067
  }
6991
7068
  const el = document.getElementById(this.elementId)
6992
7069
  if (el) {
@@ -6996,12 +7073,20 @@ class WebsyChart {
6996
7073
  }
6997
7074
  else {
6998
7075
  el.innerHTML = ''
6999
- this.svg = d3.select(el).append('svg')
7076
+ this.svg = d3.select(el).append('svg') // .attr('id', `${this.elementId}_chartContainer`)
7000
7077
  this.legendArea = d3.select(el).append('div')
7001
7078
  .attr('id', `${this.elementId}_legend`)
7002
7079
  .attr('class', 'websy-chart-legend')
7003
7080
  this.legend = new WebsyDesigns.Legend(`${this.elementId}_legend`, {})
7004
7081
  this.prep()
7082
+ // el.innerHTML += `
7083
+ // <div id="${this.elementId}_errorContainer" class='websy-vis-error-container'>
7084
+ // <div>
7085
+ // <div id="${this.elementId}_errorTitle"></div>
7086
+ // <div id="${this.elementId}_errorMessage"></div>
7087
+ // </div>
7088
+ // </div>
7089
+ // `
7005
7090
  }
7006
7091
  }
7007
7092
  else {
@@ -7028,23 +7113,34 @@ class WebsyChart {
7028
7113
  }
7029
7114
  createDomain (side) {
7030
7115
  let domain = []
7031
- /* global d3 side domain:writable */
7032
- if (typeof this.options.data[side].min !== 'undefined' && typeof this.options.data[side].max !== 'undefined') {
7033
- // domain = [this.options.data[side].min - (this.options.data[side].min * 0.1), this.options.data[side].max * 1.1]
7034
- domain = [this.options.data[side].min, this.options.data[side].max]
7035
- if (this.options.forceZero === true) {
7036
- domain = [Math.min(0, this.options.data[side].min), this.options.data[side].max]
7037
- }
7116
+ /* global d3 side domain:writable forBrush */
7117
+ // if we have a brushed domain we use that
7118
+ let xAxis = 'bottom'
7119
+ if (this.options.orientation === 'horizontal') {
7120
+ xAxis = 'left'
7038
7121
  }
7039
- if (this.options.data[side].data) {
7040
- domain = this.options.data[side].data.map(d => d.value)
7122
+ if (this.brushedDomain.length > 0 && side === xAxis && forBrush === false) {
7123
+ domain = [...this.brushedDomain]
7041
7124
  }
7042
- if (this.options.data[side].scale === 'Time') {
7043
- let min = this.options.data[side].data[0].value
7044
- let max = this.options.data[side].data[this.options.data[side].data.length - 1].value
7045
- min = this.parseX(min)
7046
- max = this.parseX(max)
7047
- domain = [min, max]
7125
+ else {
7126
+ // otherwise we create the domain
7127
+ if (typeof this.options.data[side].min !== 'undefined' && typeof this.options.data[side].max !== 'undefined') {
7128
+ // domain = [this.options.data[side].min - (this.options.data[side].min * 0.1), this.options.data[side].max * 1.1]
7129
+ domain = [this.options.data[side].min, this.options.data[side].max]
7130
+ if (this.options.forceZero === true) {
7131
+ domain = [Math.min(0, this.options.data[side].min), this.options.data[side].max]
7132
+ }
7133
+ }
7134
+ if (this.options.data[side].data) {
7135
+ domain = this.options.data[side].data.map(d => d.value)
7136
+ }
7137
+ if (this.options.data[side].scale === 'Time') {
7138
+ let min = this.options.data[side].data[0].value
7139
+ let max = this.options.data[side].data[this.options.data[side].data.length - 1].value
7140
+ min = this.parseX(min)
7141
+ max = this.parseX(max)
7142
+ domain = [min, max]
7143
+ }
7048
7144
  }
7049
7145
 
7050
7146
  return domain
@@ -7251,6 +7347,9 @@ if (this.options.data[side].scale === 'Time') {
7251
7347
  }
7252
7348
  prep () {
7253
7349
  /* global d3 WebsyDesigns */
7350
+ this.defs = this.svg.append('defs')
7351
+ this.clip = this.defs.append('clipPath').attr('id', `${this.elementId}_clip`).append('rect')
7352
+ this.brushClip = this.defs.append('clipPath').attr('id', `${this.elementId}_brushclip`).append('rect')
7254
7353
  this.leftAxisLayer = this.svg.append('g').attr('class', 'left-axis-layer')
7255
7354
  this.rightAxisLayer = this.svg.append('g').attr('class', 'right-axis-layer')
7256
7355
  this.bottomAxisLayer = this.svg.append('g').attr('class', 'bottom-axis-layer')
@@ -7267,6 +7366,14 @@ this.refLineLayer = this.svg.append('g').attr('class', 'refline-layer')
7267
7366
  this.trackingLineLayer = this.svg.append('g').attr('class', 'tracking-line-layer')
7268
7367
  this.trackingLineLayer.append('line').attr('class', 'tracking-line')
7269
7368
  this.tooltip = new WebsyDesigns.WebsyChartTooltip(this.svg)
7369
+ this.brushLayer = this.svg
7370
+ .append('g')
7371
+ // .attr(
7372
+ // 'clip-path',
7373
+ // `url(#${this.elementId.replace(/\s/g, '_')}_brushclip)`
7374
+ // )
7375
+ this.brushArea = this.brushLayer.append('g').attr('class', 'brush-area')
7376
+ this.brushLayer.append('g').attr('class', 'brush')
7270
7377
  this.eventLayer = this.svg.append('g').attr('class', 'event-line').append('rect')
7271
7378
  this.eventLayer
7272
7379
  .on('mouseout', this.handleEventMouseOut.bind(this))
@@ -7380,7 +7487,7 @@ else {
7380
7487
  this.longestBottom = this.options.data.bottom.max.toString()
7381
7488
  if (this.options.data.bottom.formatter) {
7382
7489
  this.longestBottom = this.options.data.bottom.formatter(this.options.data.bottom.max).toString()
7383
- firstBottom = this.longestBottom
7490
+ firstBottom = this.options.data.bottom.formatter(this.options.data.bottom.data[0].value).toString()
7384
7491
  }
7385
7492
  else {
7386
7493
  if (this.options.data.bottom.scale === 'Time') {
@@ -7389,6 +7496,7 @@ else {
7389
7496
  }
7390
7497
  else {
7391
7498
  this.longestBottom = this.options.data.bottom.data.reduce((a, b) => a.length > b.value.length ? a : b.value, '')
7499
+ // firstBottom = (this.options.data.bottom.data[0] || [{value: ''}]).value
7392
7500
  firstBottom = this.options.data.bottom.data[0].value
7393
7501
  }
7394
7502
  }
@@ -7464,7 +7572,7 @@ else {
7464
7572
  this.options.margin.axisLeft = Math.max(this.options.margin.axisLeft, longestBottomBounds.width / 2)
7465
7573
  }
7466
7574
  else if (((this.options.data.bottom && this.options.data.bottom.rotate) || 0) < 0 && this.options.axis.hideBottom !== true) {
7467
- this.options.margin.axisLeft = Math.max(this.options.margin.axisLeft, longestBottomBounds.width)
7575
+ this.options.margin.axisLeft = Math.max(this.options.margin.axisLeft, firstBottomWidth / 2)
7468
7576
  }
7469
7577
  else if (((this.options.data.bottom && this.options.data.bottom.rotate) || 0) > 0 && this.options.axis.hideBottom !== true) {
7470
7578
  this.options.margin.axisRight = Math.max(this.options.margin.axisRight, longestBottomBounds.width)
@@ -7494,6 +7602,23 @@ else {
7494
7602
  // Define the plot size
7495
7603
  this.plotWidth = this.width - this.options.margin.legendLeft - this.options.margin.legendRight - this.options.margin.left - this.options.margin.right - this.options.margin.axisLeft - this.options.margin.axisRight
7496
7604
  this.plotHeight = this.height - this.options.margin.legendTop - this.options.margin.legendBottom - this.options.margin.top - this.options.margin.bottom - this.options.margin.axisBottom - this.options.margin.axisTop
7605
+ if (this.options.orientation === 'vertical') {
7606
+ if (this.options.maxBandWidth) {
7607
+ this.plotWidth = Math.min(this.plotWidth, (this.options.data.bottom.data || []).length * this.options.maxBandWidth)
7608
+ }
7609
+ // some if to check if brushing is needed
7610
+ if (this.plotWidth / this.options.data.bottom.data.length < this.options.minBandWidth) {
7611
+ this.brushNeeded = true
7612
+ this.plotHeight -= this.options.brushHeight
7613
+ }
7614
+ }
7615
+ else {
7616
+ // some if to check if brushing is needed
7617
+ if (this.plotHeight / this.options.data.left.data.length < this.options.minBandWidth) {
7618
+ this.brushNeeded = true
7619
+ this.plotWidth -= this.options.brushHeight
7620
+ }
7621
+ }
7497
7622
  // Translate the layers
7498
7623
  this.leftAxisLayer
7499
7624
  .attr('transform', `translate(${this.options.margin.left + this.options.margin.axisLeft}, ${this.options.margin.top + this.options.margin.axisTop})`)
@@ -7526,6 +7651,12 @@ else {
7526
7651
  .attr('transform', `translate(${this.options.margin.left + this.options.margin.axisLeft}, ${this.options.margin.top + this.options.margin.axisTop})`)
7527
7652
  this.trackingLineLayer
7528
7653
  .attr('transform', `translate(${this.options.margin.left + this.options.margin.axisLeft}, ${this.options.margin.top + this.options.margin.axisTop})`)
7654
+ this.brushLayer
7655
+ .attr('transform', `translate(${this.options.margin.left + this.options.margin.axisLeft}, ${this.options.margin.top + this.options.margin.axisTop + this.plotHeight + longestBottomBounds.height})`)
7656
+ this.brushClip
7657
+ .attr('transform', `translate(${this.options.margin.left + this.options.margin.axisLeft}, ${this.options.margin.top + this.options.margin.axisTop + this.plotHeight + longestBottomBounds.height})`)
7658
+ .attr('width', this.plotWidth)
7659
+ .attr('height', this.options.brushHeight)
7529
7660
  this.eventLayer
7530
7661
  .attr('transform', `translate(${this.options.margin.left + this.options.margin.axisLeft}, ${this.options.margin.top + this.options.margin.axisTop})`)
7531
7662
  let that = this
@@ -7537,16 +7668,110 @@ else {
7537
7668
  .attr('fill-opacity', '0')
7538
7669
  // this.tooltip.transform(this.options.margin.left + this.options.margin.axisLeft, this.options.margin.top + this.options.margin.axisTop)
7539
7670
  // Configure the bottom axis
7540
- let bottomDomain = this.createDomain('bottom')
7671
+ let bottomDomain = this.createDomain('bottom')
7672
+ let bottomBrushDomain = this.createDomain('bottom', true)
7541
7673
  this.bottomAxis = d3[`scale${this.options.data.bottom.scale || 'Band'}`]()
7542
7674
  .domain(bottomDomain)
7543
- .range([0, this.plotWidth])
7675
+ .range([0, this.plotWidth])
7676
+ if (!this.brushInitialized) {
7677
+ this.bottomBrushAxis = d3[`scale${this.options.data.bottom.scale || 'Band'}`]()
7678
+ .domain(bottomBrushDomain)
7679
+ .range([0, this.plotWidth])
7680
+ }
7544
7681
  if (this.bottomAxis.nice) {
7545
7682
  // this.bottomAxis.nice()
7546
7683
  }
7547
7684
  if (this.bottomAxis.padding && this.options.data.bottom.padding) {
7548
7685
  this.bottomAxis.padding(this.options.data.bottom.padding || 0)
7549
7686
  }
7687
+ // BRUSH
7688
+ let brushMethod = `brushX`
7689
+ let brushLength = this.plotWidth
7690
+ let brushEnd = this.plotWidth
7691
+ let brushThickness = this.options.brushHeight
7692
+ if (this.options.orientation === 'horizontal') {
7693
+ brushMethod = 'brushY'
7694
+ brushLength = this.options.brushHeight
7695
+ brushThickness = this.plotHeight
7696
+ }
7697
+ else {
7698
+ if (brushLength / bottomDomain.length < this.options.minBandWidth) {
7699
+ brushEnd = this.plotWidth * ((this.plotWidth / this.options.minBandWidth) / bottomDomain.length)
7700
+ }
7701
+ }
7702
+ this.brush = d3[brushMethod]()
7703
+ .extent([
7704
+ [0, 0],
7705
+ [brushLength, brushThickness]
7706
+ ])
7707
+ .on('brush end', this.brushed)
7708
+ const brushResizePath = d => {
7709
+ let e = +(d.type === 'e')
7710
+ let x = e ? 1 : -1
7711
+ let y = this.options.brushHeight
7712
+ return (
7713
+ 'M' +
7714
+ 0.5 * x +
7715
+ ',' +
7716
+ y +
7717
+ 'A6,6 0 0 ' +
7718
+ e +
7719
+ ' ' +
7720
+ 6.5 * x +
7721
+ ',' +
7722
+ (y + 6) +
7723
+ 'V' +
7724
+ (2 * y - 6) +
7725
+ 'A6,6 0 0 ' +
7726
+ e +
7727
+ ' ' +
7728
+ 0.5 * x +
7729
+ ',' +
7730
+ 2 * y +
7731
+ 'Z' +
7732
+ 'M' +
7733
+ 2.5 * x +
7734
+ ',' +
7735
+ (y + 8) +
7736
+ 'V' +
7737
+ (2 * y - 8) +
7738
+ 'M' +
7739
+ 4.5 * x +
7740
+ ',' +
7741
+ (y + 8) +
7742
+ 'V' +
7743
+ (2 * y - 8)
7744
+ )
7745
+ }
7746
+ this.brushHandle = this.brushLayer
7747
+ .select('.brush')
7748
+ .selectAll('.handle--custom')
7749
+ .remove()
7750
+ this.brushHandle = this.brushLayer
7751
+ .select('.brush')
7752
+ .selectAll('.handle--custom')
7753
+ .data([{ type: 'w' }, { type: 'e' }])
7754
+ .enter()
7755
+ .append('path')
7756
+ .attr('class', 'handle--custom')
7757
+ .attr('stroke', 'transparent')
7758
+ .attr('fill', 'transparent')
7759
+ .attr('cursor', 'ew-resize')
7760
+ .attr('d', brushResizePath)
7761
+ // BRUSH END
7762
+ // this.brushArea.selectAll('*').remove()
7763
+ if (this.brushNeeded) {
7764
+ if (!this.brushInitialized) {
7765
+ this.brushInitialized = true
7766
+ this.brushLayer
7767
+ .select('.brush')
7768
+ .call(this.brush)
7769
+ .call(this.brush.move, [0, brushEnd])
7770
+ }
7771
+ }
7772
+ else {
7773
+ this.brushLayer.selectAll().remove()
7774
+ }
7550
7775
  if (this.options.margin.axisBottom > 0) {
7551
7776
  let timeFormatPattern = ''
7552
7777
  let tickDefinition
@@ -7607,15 +7832,12 @@ else {
7607
7832
  tickDefinition = this.options.data.bottom.ticks || 5
7608
7833
  }
7609
7834
  this.options.calculatedTimeFormatPattern = timeFormatPattern
7610
- let bAxisFunc = d3.axisBottom(this.bottomAxis)
7611
- // .ticks(this.options.data.bottom.ticks || Math.min(this.options.data.bottom.data.length, 5))
7612
- .ticks(tickDefinition)
7613
- // console.log('tickDefinition', tickDefinition)
7614
- // console.log(bAxisFunc)
7835
+ this.bAxisFunc = d3.axisBottom(this.bottomAxis)
7836
+ .ticks(tickDefinition)
7615
7837
  if (this.options.data.bottom.formatter) {
7616
- bAxisFunc.tickFormat(d => this.options.data.bottom.formatter(d))
7838
+ this.bAxisFunc.tickFormat(d => this.options.data.bottom.formatter(d))
7617
7839
  }
7618
- this.bottomAxisLayer.call(bAxisFunc)
7840
+ this.bottomAxisLayer.call(this.bAxisFunc)
7619
7841
  // console.log(this.bottomAxisLayer.ticks)
7620
7842
  if (this.options.data.bottom.rotate) {
7621
7843
  this.bottomAxisLayer.selectAll('text')
@@ -7625,11 +7847,15 @@ else {
7625
7847
  }
7626
7848
  }
7627
7849
  // Configure the left axis
7628
- let leftDomain = this.createDomain('left')
7850
+ let leftDomain = this.createDomain('left')
7851
+ let leftBrushDomain = this.createDomain('left', true)
7629
7852
  let rightDomain = this.createDomain('right')
7630
7853
  this.leftAxis = d3[`scale${this.options.data.left.scale || 'Linear'}`]()
7631
7854
  .domain(leftDomain)
7632
7855
  .range([this.plotHeight, 0])
7856
+ this.leftBrushAxis = d3[`scale${this.options.data.left.scale || 'Linear'}`]()
7857
+ .domain(leftBrushDomain)
7858
+ .range([this.options.brushHeight, 0])
7633
7859
  if (this.leftAxis.padding && this.options.data.left.padding) {
7634
7860
  this.leftAxis.padding(this.options.data.left.padding || 0)
7635
7861
  }
@@ -7698,7 +7924,7 @@ else {
7698
7924
  if (this.options.margin.axisRight > 0 && (this.options.data.right.min !== 0 || this.options.data.right.max !== 0)) {
7699
7925
  this.rightAxisLayer.call(
7700
7926
  d3.axisRight(this.rightAxis)
7701
- .ticks(this.options.data.left.ticks || 5)
7927
+ .ticks(this.options.data.right.ticks || 5)
7702
7928
  .tickFormat(d => {
7703
7929
  if (this.options.data.right.formatter) {
7704
7930
  d = this.options.data.right.formatter(d)
@@ -7745,25 +7971,29 @@ else {
7745
7971
  this[`remove${this.renderedKeys[key]}`](key)
7746
7972
  }
7747
7973
  }
7748
- // Draw the series data
7749
- this.renderedKeys = {}
7750
- this.options.data.series.forEach((series, index) => {
7751
- if (!series.key) {
7752
- series.key = this.createIdentity()
7753
- }
7754
- if (!series.color) {
7755
- series.color = this.options.colors[index % this.options.colors.length]
7756
- }
7757
- this[`render${series.type || 'bar'}`](series, index)
7758
- this.renderLabels(series, index)
7759
- this.renderedKeys[series.key] = series.type
7760
- })
7761
- if (this.options.refLines && this.options.refLines.length > 0) {
7762
- this.options.refLines.forEach(l => this.renderRefLine(l))
7763
- }
7974
+ this.renderComponents()
7764
7975
  }
7765
7976
  }
7766
7977
 
7978
+ }
7979
+ renderComponents () {
7980
+ // Draw the series data
7981
+ this.renderedKeys = {}
7982
+ this.options.data.series.forEach((series, index) => {
7983
+ if (!series.key) {
7984
+ series.key = this.createIdentity()
7985
+ }
7986
+ if (!series.color) {
7987
+ series.color = this.options.colors[index % this.options.colors.length]
7988
+ }
7989
+ this[`render${series.type || 'bar'}`](series, index)
7990
+ this.renderLabels(series, index)
7991
+ this.renderedKeys[series.key] = series.type
7992
+ })
7993
+ if (this.options.refLines && this.options.refLines.length > 0) {
7994
+ this.options.refLines.forEach(l => this.renderRefLine(l))
7995
+ }
7996
+
7767
7997
  }
7768
7998
  renderarea (series, index) {
7769
7999
  /* global d3 series index */
@@ -7822,74 +8052,111 @@ areas.enter().append('path')
7822
8052
  let xAxis = 'bottom'
7823
8053
  let yAxis = 'left'
7824
8054
  let bars = this.barLayer.selectAll(`.bar_${series.key}`).data(series.data)
8055
+ let brushBars = this.brushArea.selectAll(`.bar_${series.key}`).data(series.data)
7825
8056
  let acummulativeY = new Array(this.options.data.series.length).fill(0)
7826
8057
  if (this.options.orientation === 'horizontal') {
7827
8058
  xAxis = 'left'
7828
8059
  yAxis = 'bottom'
7829
8060
  }
7830
- let barWidth = this[`${xAxis}Axis`].bandwidth()
7831
- let groupedBarWidth = (barWidth - 10) / this.options.data.series.length
7832
8061
  // if (this.options.data.series.length > 1 && this.options.grouping === 'grouped') {
7833
8062
  // barWidth = barWidth / this.options.data.series.length - 4
7834
8063
  // }
7835
- function getBarHeight (d, i) {
8064
+ function getBarHeight (d, i, heightBounds, yAxis, xAxis) {
8065
+ let barWidth = this[`${xAxis}Axis`].bandwidth()
8066
+ let groupedBarWidth = (barWidth - 10) / this.options.data.series.length
8067
+ let output
7836
8068
  if (this.options.orientation === 'horizontal') {
7837
- return barWidth
8069
+ output = barWidth
7838
8070
  }
7839
8071
  else {
7840
- return this[`${yAxis}Axis`](d.y.value)
8072
+ if (!getBarX.call(this, d, i, xAxis)) {
8073
+ return null
8074
+ }
8075
+ output = (this[`${yAxis}Axis`](0)) - this[`${yAxis}Axis`](Math.abs(d.y.value))
8076
+ }
8077
+ if (isNaN(output)) {
8078
+ return null
7841
8079
  }
8080
+ return output
7842
8081
  }
7843
- function getBarWidth (d, i) {
8082
+ function getBarWidth (d, i, xAxis) {
8083
+ let barWidth = this[`${xAxis}Axis`].bandwidth()
8084
+ let groupedBarWidth = (barWidth - (xAxis.indexOf('Brush') === -1 ? 10 : 2)) / this.options.data.series.length
8085
+ let output
7844
8086
  if (this.options.orientation === 'horizontal') {
7845
8087
  let width = this[`${yAxis}Axis`](d.y.value)
7846
8088
  acummulativeY[d.y.index] += width
7847
- return width
8089
+ output = Math.max(1, width)
7848
8090
  }
7849
8091
  else {
8092
+ if (!getBarX.call(this, d, i, xAxis)) {
8093
+ return null
8094
+ }
7850
8095
  if (this.options.grouping === 'grouped') {
7851
- return groupedBarWidth
8096
+ output = Math.max(1, groupedBarWidth)
8097
+ }
8098
+ else {
8099
+ output = Math.max(1, barWidth)
7852
8100
  }
7853
- return barWidth
7854
8101
  }
8102
+ if (isNaN(output)) {
8103
+ return 0
8104
+ }
8105
+ return output
7855
8106
  }
7856
- function getBarX (d, i) {
8107
+ function getBarX (d, i, xAxis) {
8108
+ let barWidth = this[`${xAxis}Axis`].bandwidth()
8109
+ let groupedBarWidth = (barWidth - (xAxis.indexOf('Brush') === -1 ? 10 : 2)) / this.options.data.series.length
8110
+ let output
7857
8111
  if (this.options.orientation === 'horizontal') {
7858
8112
  if (this.options.grouping === 'stacked') {
7859
- return this[`${yAxis}Axis`](d.y.accumulative)
8113
+ output = this[`${yAxis}Axis`](d.y.accumulative)
7860
8114
  }
7861
8115
  else {
7862
- return 0
8116
+ output = 0
7863
8117
  }
7864
8118
  }
7865
8119
  else {
7866
- let adjustment = this.options.data[xAxis].scale === 'Time' ? 0 : this[`${xAxis}Axis`].bandwidth() / 2
8120
+ let adjustment = this.options.data[xAxis.replace('Brush', '')].scale === 'Time' ? 0 : this[`${xAxis}Axis`].bandwidth() / 2
7867
8121
  if (this.options.grouping === 'grouped') {
7868
- let barAdjustment = groupedBarWidth * index + 5 // + (index > 0 ? 4 : 0)
7869
- return this[`${xAxis}Axis`](this.parseX(d.x.value)) + barAdjustment
8122
+ let barAdjustment = groupedBarWidth * index + (xAxis.indexOf('Brush') === -1 ? 5 : 1) // + (index > 0 ? 4 : 0)
8123
+ output = this[`${xAxis}Axis`](this.parseX(d.x.value)) + barAdjustment
7870
8124
  }
7871
8125
  else {
7872
- return this[`${xAxis}Axis`](this.parseX(d.x.value)) + (i * barWidth) + adjustment
8126
+ // output = this[`${xAxis}Axis`](this.parseX(d.x.value)) + (i * barWidth) + adjustment
8127
+ output = this[`${xAxis}Axis`](this.parseX(d.x.value)) // + (i * barWidth)
7873
8128
  }
7874
8129
  }
8130
+ if (isNaN(output)) {
8131
+ return null
8132
+ }
8133
+ return output
7875
8134
  }
7876
- function getBarY (d, i) {
8135
+ function getBarY (d, i, heightBounds, yAxis, xAxis) {
8136
+ let barWidth = this[`${xAxis}Axis`].bandwidth()
8137
+ let groupedBarWidth = (barWidth - 10) / this.options.data.series.length
8138
+ let output
7877
8139
  if (this.options.orientation === 'horizontal') {
7878
8140
  if (this.options.grouping !== 'grouped') {
7879
- return this[`${xAxis}Axis`](this.parseX(d.x.value))
8141
+ output = this[`${xAxis}Axis`](this.parseX(d.x.value))
7880
8142
  }
7881
8143
  else {
7882
- return this[`${xAxis}Axis`](this.parseX(d.x.value)) + ((d.y.index || i) * barWidth)
8144
+ output = this[`${xAxis}Axis`](this.parseX(d.x.value)) + ((d.y.index || i) * barWidth)
7883
8145
  }
7884
8146
  }
7885
8147
  else {
7886
8148
  if (this.options.grouping === 'stacked') {
7887
- return this[`${yAxis}Axis`](d.y.accumulative)
8149
+ output = heightBounds - this[`${yAxis}Axis`](d.y.accumulative)
7888
8150
  }
7889
8151
  else {
7890
- return this.plotHeight - getBarHeight.call(this, d, i)
8152
+ let h = getBarHeight.call(this, d, i, heightBounds, yAxis, xAxis)
8153
+ output = (this[`${yAxis}Axis`](0)) - (h * (d.y.value < 0 ? 0 : 1))
7891
8154
  }
7892
8155
  }
8156
+ if (isNaN(output)) {
8157
+ return null
8158
+ }
8159
+ return output
7893
8160
  }
7894
8161
  bars
7895
8162
  .exit()
@@ -7898,26 +8165,56 @@ bars
7898
8165
  .remove()
7899
8166
 
7900
8167
  bars
7901
- .attr('width', getBarWidth.bind(this))
7902
- .attr('height', getBarHeight.bind(this))
7903
- .attr('x', getBarX.bind(this))
7904
- .attr('y', getBarY.bind(this))
7905
- .transition(this.transition)
8168
+ .attr('width', (d, i) => getBarWidth.call(this, d, i, xAxis))
8169
+ .attr('height', (d, i) => getBarHeight.call(this, d, i, this.plotHeight, yAxis, xAxis))
8170
+ .attr('x', (d, i) => getBarX.call(this, d, i, xAxis))
8171
+ .attr('y', (d, i) => getBarY.call(this, d, i, this.plotHeight, yAxis, xAxis))
8172
+ // .transition(this.transition)
7906
8173
  .attr('fill', d => d.y.color || d.color || series.color)
7907
8174
 
7908
8175
  bars
7909
8176
  .enter()
7910
8177
  .append('rect')
7911
- .attr('width', getBarWidth.bind(this))
7912
- .attr('height', getBarHeight.bind(this))
7913
- .attr('x', getBarX.bind(this))
7914
- .attr('y', getBarY.bind(this))
8178
+ .attr('width', (d, i) => getBarWidth.call(this, d, i, xAxis))
8179
+ .attr('height', (d, i) => getBarHeight.call(this, d, i, this.plotHeight, yAxis, xAxis))
8180
+ .attr('x', (d, i) => getBarX.call(this, d, i, xAxis))
8181
+ .attr('y', (d, i) => getBarY.call(this, d, i, this.plotHeight, yAxis, xAxis))
7915
8182
  // .transition(this.transition)
7916
8183
  .attr('fill', d => d.y.color || d.color || series.color)
7917
8184
  .attr('class', d => {
7918
8185
  return `bar bar_${series.key}`
7919
8186
  })
7920
8187
 
8188
+ if (!this.brushBarsInitialized[series.key]) {
8189
+ this.brushBarsInitialized[series.key] = true
8190
+ brushBars
8191
+ .exit()
8192
+ .transition(this.transition)
8193
+ .style('fill-opacity', 1e-6)
8194
+ .remove()
8195
+
8196
+ brushBars
8197
+ .attr('width', (d, i) => getBarWidth.call(this, d, i, `${xAxis}Brush`))
8198
+ .attr('height', (d, i) => getBarHeight.call(this, d, i, this.options.brushHeight, `${yAxis}Brush`, `${xAxis}Brush`))
8199
+ .attr('x', (d, i) => getBarX.call(this, d, i, `${xAxis}Brush`))
8200
+ .attr('y', (d, i) => getBarY.call(this, d, i, this.options.brushHeight, `${yAxis}Brush`, `${xAxis}Brush`))
8201
+ // .transition(this.transition)
8202
+ .attr('fill', d => d.y.color || d.color || series.color)
8203
+
8204
+ brushBars
8205
+ .enter()
8206
+ .append('rect')
8207
+ .attr('width', (d, i) => getBarWidth.call(this, d, i, `${xAxis}Brush`))
8208
+ .attr('height', (d, i) => getBarHeight.call(this, d, i, this.options.brushHeight, `${yAxis}Brush`, `${xAxis}Brush`))
8209
+ .attr('x', (d, i) => getBarX.call(this, d, i, `${xAxis}Brush`))
8210
+ .attr('y', (d, i) => getBarY.call(this, d, i, this.options.brushHeight, `${yAxis}Brush`, `${xAxis}Brush`))
8211
+ // .transition(this.transition)
8212
+ .attr('fill', d => d.y.color || d.color || series.color)
8213
+ .attr('class', d => {
8214
+ return `bar bar_${series.key}`
8215
+ })
8216
+ }
8217
+
7921
8218
  }
7922
8219
  removebar (key) {
7923
8220
  /* global key d3 */
@@ -8307,6 +8604,44 @@ if (el) {
8307
8604
  }
8308
8605
 
8309
8606
  }
8607
+ hideError () {
8608
+ const el = document.getElementById(`${this.elementId}`)
8609
+ if (el) {
8610
+ el.classList.remove('has-error')
8611
+ }
8612
+ // const chartEl = document.getElementById(`${this.elementId}_chartContainer`)
8613
+ // chartEl.classList.remove('hidden')
8614
+ this.svg.classed('hidden', false)
8615
+ const containerEl = document.getElementById(`${this.elementId}_errorContainer`)
8616
+ if (containerEl) {
8617
+ containerEl.classList.remove('active')
8618
+ }
8619
+ }
8620
+ showError (options) {
8621
+ const el = document.getElementById(`${this.elementId}`)
8622
+ if (el) {
8623
+ el.classList.add('has-error')
8624
+ }
8625
+ // const chartEl = document.getElementById(`${this.elementId}_chartContainer`)
8626
+ // chartEl.classList.add('hidden')
8627
+ this.svg.classed('hidden', true)
8628
+ const containerEl = document.getElementById(`${this.elementId}_errorContainer`)
8629
+ if (containerEl) {
8630
+ containerEl.classList.add('active')
8631
+ }
8632
+ if (options.title) {
8633
+ const titleEl = document.getElementById(`${this.elementId}_errorTitle`)
8634
+ if (titleEl) {
8635
+ titleEl.innerHTML = options.title
8636
+ }
8637
+ }
8638
+ if (options.message) {
8639
+ const messageEl = document.getElementById(`${this.elementId}_errorMessage`)
8640
+ if (messageEl) {
8641
+ messageEl.innerHTML = options.message
8642
+ }
8643
+ }
8644
+ }
8310
8645
  }
8311
8646
 
8312
8647
  class WebsyLegend {