@websy/websy-designs 1.4.32 → 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.
@@ -231,7 +231,7 @@ class ButtonGroup {
231
231
  if (el && this.options.items) {
232
232
  el.innerHTML = this.options.items.map((t, i) => {
233
233
  let activeClass = ''
234
- if (this.options.activeItem && this.options.activeItem !== -1) {
234
+ if (this.options.activeItem !== -1) {
235
235
  activeClass = i === this.options.activeItem ? 'active' : 'inactive'
236
236
  }
237
237
  return `
@@ -6158,6 +6158,10 @@ class WebsyTable3 {
6158
6158
  headEl.style.width = 'initial'
6159
6159
  bodyEl.style.width = 'initial'
6160
6160
  this.sizes.bodyHeight = this.sizes.table.height - (this.sizes.header.height + this.sizes.total.height)
6161
+ if (this.options.maxHeight) {
6162
+ let requiredHeight = ((this.totalRowCount || 9) + 1) * this.sizes.cellHeight
6163
+ this.sizes.bodyHeight = Math.min(requiredHeight, this.options.maxHeight - (this.sizes.header.height + this.sizes.total.height))
6164
+ }
6161
6165
  this.sizes.rowsToRender = Math.ceil(this.sizes.bodyHeight / this.sizes.cellHeight)
6162
6166
  this.sizes.rowsToRenderPrecise = this.sizes.bodyHeight / this.sizes.cellHeight
6163
6167
  this.startRow = 0
@@ -6344,7 +6348,13 @@ class WebsyTable3 {
6344
6348
  }
6345
6349
  let bodyEl = document.getElementById(`${this.elementId}_tableBody`)
6346
6350
  // bodyEl.innerHTML = this.buildBodyHtml(data, true)
6347
- bodyEl.style.height = `calc(100% - ${this.sizes.header.height}px - ${this.sizes.total.height}px)`
6351
+ // if (this.options.maxHeight) {
6352
+ // bodyEl.style.height = `${this.options.maxHeight - this.sizes.header.height - this.sizes.total.height}px`
6353
+ // }
6354
+ // else {
6355
+ // bodyEl.style.height = `calc(100% - ${this.sizes.header.height}px - ${this.sizes.total.height}px)`
6356
+ // }
6357
+ bodyEl.style.height = `${this.sizes.bodyHeight}px`
6348
6358
  if (this.options.virtualScroll === true) {
6349
6359
  // set the scroll element positions
6350
6360
  let vScrollEl = document.getElementById(`${this.elementId}_vScrollContainer`)
@@ -6542,7 +6552,9 @@ class WebsyChart {
6542
6552
  showTooltip: true,
6543
6553
  showLegend: false,
6544
6554
  legendPosition: 'bottom',
6545
- tooltipWidth: 200
6555
+ tooltipWidth: 200,
6556
+ brushHeight: 50,
6557
+ minBandWidth: 30
6546
6558
  }
6547
6559
  this.elementId = elementId
6548
6560
  this.options = Object.assign({}, DEFAULTS, options)
@@ -6551,15 +6563,21 @@ class WebsyChart {
6551
6563
  this.topAxis = null
6552
6564
  this.bottomAxis = null
6553
6565
  this.renderedKeys = {}
6566
+ this.brushedDomain = []
6567
+ this.brushBarsInitialized = {}
6554
6568
  if (!elementId) {
6555
6569
  console.log('No element Id provided for Websy Chart')
6556
6570
  return
6557
6571
  }
6558
- this.invertOverride = (input, input2) => {
6559
- let xAxis = 'bottomAxis'
6572
+ this.invertOverride = (input, input2, forBrush = false) => {
6573
+ let xAxis = 'bottom'
6560
6574
  if (this.options.orientation === 'horizontal') {
6561
- xAxis = 'leftAxis'
6575
+ xAxis = 'left'
6576
+ }
6577
+ if (forBrush === true) {
6578
+ xAxis += 'Brush'
6562
6579
  }
6580
+ xAxis += 'Axis'
6563
6581
  let width = this[xAxis].step()
6564
6582
  let output
6565
6583
  let domain = [...this[xAxis].domain()]
@@ -6575,6 +6593,65 @@ class WebsyChart {
6575
6593
  }
6576
6594
  }
6577
6595
  return output
6596
+ }
6597
+ let that = this
6598
+ this.brushed = function (event) {
6599
+ console.log('brushing', event)
6600
+ that.brushedDomain = []
6601
+ let xAxis = 'bottom'
6602
+ let xAxisCaps = 'Bottom'
6603
+ if (that.options.orientation === 'horizontal') {
6604
+ xAxis = 'left'
6605
+ xAxisCaps = 'Left'
6606
+ }
6607
+ if (!that[`${xAxis}Axis`].invert) {
6608
+ that[`${xAxis}Axis`].invert = that.invertOverride
6609
+ }
6610
+ let s = event.selection || that[`${xAxis}Axis`].range()
6611
+ if (!event.selection || event.selection.length === 0) {
6612
+ that.brushLayer
6613
+ .select('.brush')
6614
+ .call(that.brush)
6615
+ .call(that.brush.move, s)
6616
+ return
6617
+ }
6618
+ if (that.options.data[xAxis].scale && that.options.data[xAxis].scale === 'Time') {
6619
+ that.brushedDomain = s.map(that[`${xAxis}BrushAxis`].invert, that[[`${xAxis}Axis`]])
6620
+ }
6621
+ else {
6622
+ let startEndOrdinal = s.map((a, b) => that.bottomAxis.invert(a, b, true), that.bottomBrushAxis)
6623
+ if (
6624
+ startEndOrdinal &&
6625
+ startEndOrdinal.length === 2 &&
6626
+ typeof startEndOrdinal[0] !== 'undefined' &&
6627
+ typeof startEndOrdinal[1] !== 'undefined'
6628
+ ) {
6629
+ let domain = []
6630
+ let domainValues = [...that[`${xAxis}BrushAxis`].domain()]
6631
+ for (let i = startEndOrdinal[0]; i < startEndOrdinal[1] + 1; i++) {
6632
+ // domain.push(that.xRange[i])
6633
+ that.brushedDomain.push(domainValues[i])
6634
+ }
6635
+ }
6636
+ }
6637
+ if (that.brushedDomain.length > 0) {
6638
+ that[`${xAxis}Axis`].domain(that.brushedDomain)
6639
+ that[`${xAxis}AxisLayer`].call(
6640
+ d3[`axis${xAxisCaps}`](that[`${xAxis}Axis`])
6641
+ )
6642
+ }
6643
+ if (that.leftAxis && that.bottomAxis) {
6644
+ that.renderComponents()
6645
+ if (that.options.orientation === 'vertical') {
6646
+ // that.bottomAxisLayer.call(that.bAxisFunc)
6647
+ if (that.options.data.bottom.rotate) {
6648
+ that.bottomAxisLayer.selectAll('text')
6649
+ .attr('transform', `rotate(${((that.options.data.bottom && that.options.data.bottom.rotate) || 0)})`)
6650
+ .style('text-anchor', `${((that.options.data.bottom && that.options.data.bottom.rotate) || 0) === 0 ? 'middle' : 'end'}`)
6651
+ .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`)
6652
+ }
6653
+ }
6654
+ }
6578
6655
  }
6579
6656
  const el = document.getElementById(this.elementId)
6580
6657
  if (el) {
@@ -6584,12 +6661,20 @@ class WebsyChart {
6584
6661
  }
6585
6662
  else {
6586
6663
  el.innerHTML = ''
6587
- this.svg = d3.select(el).append('svg')
6664
+ this.svg = d3.select(el).append('svg') // .attr('id', `${this.elementId}_chartContainer`)
6588
6665
  this.legendArea = d3.select(el).append('div')
6589
6666
  .attr('id', `${this.elementId}_legend`)
6590
6667
  .attr('class', 'websy-chart-legend')
6591
6668
  this.legend = new WebsyDesigns.Legend(`${this.elementId}_legend`, {})
6592
6669
  this.prep()
6670
+ // el.innerHTML += `
6671
+ // <div id="${this.elementId}_errorContainer" class='websy-vis-error-container'>
6672
+ // <div>
6673
+ // <div id="${this.elementId}_errorTitle"></div>
6674
+ // <div id="${this.elementId}_errorMessage"></div>
6675
+ // </div>
6676
+ // </div>
6677
+ // `
6593
6678
  }
6594
6679
  }
6595
6680
  else {
@@ -6616,23 +6701,34 @@ class WebsyChart {
6616
6701
  }
6617
6702
  createDomain (side) {
6618
6703
  let domain = []
6619
- /* global d3 side domain:writable */
6620
- if (typeof this.options.data[side].min !== 'undefined' && typeof this.options.data[side].max !== 'undefined') {
6621
- // domain = [this.options.data[side].min - (this.options.data[side].min * 0.1), this.options.data[side].max * 1.1]
6622
- domain = [this.options.data[side].min, this.options.data[side].max]
6623
- if (this.options.forceZero === true) {
6624
- domain = [Math.min(0, this.options.data[side].min), this.options.data[side].max]
6625
- }
6704
+ /* global d3 side domain:writable forBrush */
6705
+ // if we have a brushed domain we use that
6706
+ let xAxis = 'bottom'
6707
+ if (this.options.orientation === 'horizontal') {
6708
+ xAxis = 'left'
6626
6709
  }
6627
- if (this.options.data[side].data) {
6628
- domain = this.options.data[side].data.map(d => d.value)
6710
+ if (this.brushedDomain.length > 0 && side === xAxis && forBrush === false) {
6711
+ domain = [...this.brushedDomain]
6629
6712
  }
6630
- if (this.options.data[side].scale === 'Time') {
6631
- let min = this.options.data[side].data[0].value
6632
- let max = this.options.data[side].data[this.options.data[side].data.length - 1].value
6633
- min = this.parseX(min)
6634
- max = this.parseX(max)
6635
- domain = [min, max]
6713
+ else {
6714
+ // otherwise we create the domain
6715
+ if (typeof this.options.data[side].min !== 'undefined' && typeof this.options.data[side].max !== 'undefined') {
6716
+ // domain = [this.options.data[side].min - (this.options.data[side].min * 0.1), this.options.data[side].max * 1.1]
6717
+ domain = [this.options.data[side].min, this.options.data[side].max]
6718
+ if (this.options.forceZero === true) {
6719
+ domain = [Math.min(0, this.options.data[side].min), this.options.data[side].max]
6720
+ }
6721
+ }
6722
+ if (this.options.data[side].data) {
6723
+ domain = this.options.data[side].data.map(d => d.value)
6724
+ }
6725
+ if (this.options.data[side].scale === 'Time') {
6726
+ let min = this.options.data[side].data[0].value
6727
+ let max = this.options.data[side].data[this.options.data[side].data.length - 1].value
6728
+ min = this.parseX(min)
6729
+ max = this.parseX(max)
6730
+ domain = [min, max]
6731
+ }
6636
6732
  }
6637
6733
 
6638
6734
  return domain
@@ -6839,6 +6935,9 @@ if (this.options.data[side].scale === 'Time') {
6839
6935
  }
6840
6936
  prep () {
6841
6937
  /* global d3 WebsyDesigns */
6938
+ this.defs = this.svg.append('defs')
6939
+ this.clip = this.defs.append('clipPath').attr('id', `${this.elementId}_clip`).append('rect')
6940
+ this.brushClip = this.defs.append('clipPath').attr('id', `${this.elementId}_brushclip`).append('rect')
6842
6941
  this.leftAxisLayer = this.svg.append('g').attr('class', 'left-axis-layer')
6843
6942
  this.rightAxisLayer = this.svg.append('g').attr('class', 'right-axis-layer')
6844
6943
  this.bottomAxisLayer = this.svg.append('g').attr('class', 'bottom-axis-layer')
@@ -6855,6 +6954,14 @@ this.refLineLayer = this.svg.append('g').attr('class', 'refline-layer')
6855
6954
  this.trackingLineLayer = this.svg.append('g').attr('class', 'tracking-line-layer')
6856
6955
  this.trackingLineLayer.append('line').attr('class', 'tracking-line')
6857
6956
  this.tooltip = new WebsyDesigns.WebsyChartTooltip(this.svg)
6957
+ this.brushLayer = this.svg
6958
+ .append('g')
6959
+ // .attr(
6960
+ // 'clip-path',
6961
+ // `url(#${this.elementId.replace(/\s/g, '_')}_brushclip)`
6962
+ // )
6963
+ this.brushArea = this.brushLayer.append('g').attr('class', 'brush-area')
6964
+ this.brushLayer.append('g').attr('class', 'brush')
6858
6965
  this.eventLayer = this.svg.append('g').attr('class', 'event-line').append('rect')
6859
6966
  this.eventLayer
6860
6967
  .on('mouseout', this.handleEventMouseOut.bind(this))
@@ -6968,7 +7075,7 @@ else {
6968
7075
  this.longestBottom = this.options.data.bottom.max.toString()
6969
7076
  if (this.options.data.bottom.formatter) {
6970
7077
  this.longestBottom = this.options.data.bottom.formatter(this.options.data.bottom.max).toString()
6971
- firstBottom = this.longestBottom
7078
+ firstBottom = this.options.data.bottom.formatter(this.options.data.bottom.data[0].value).toString()
6972
7079
  }
6973
7080
  else {
6974
7081
  if (this.options.data.bottom.scale === 'Time') {
@@ -6977,6 +7084,7 @@ else {
6977
7084
  }
6978
7085
  else {
6979
7086
  this.longestBottom = this.options.data.bottom.data.reduce((a, b) => a.length > b.value.length ? a : b.value, '')
7087
+ // firstBottom = (this.options.data.bottom.data[0] || [{value: ''}]).value
6980
7088
  firstBottom = this.options.data.bottom.data[0].value
6981
7089
  }
6982
7090
  }
@@ -7052,7 +7160,7 @@ else {
7052
7160
  this.options.margin.axisLeft = Math.max(this.options.margin.axisLeft, longestBottomBounds.width / 2)
7053
7161
  }
7054
7162
  else if (((this.options.data.bottom && this.options.data.bottom.rotate) || 0) < 0 && this.options.axis.hideBottom !== true) {
7055
- this.options.margin.axisLeft = Math.max(this.options.margin.axisLeft, longestBottomBounds.width)
7163
+ this.options.margin.axisLeft = Math.max(this.options.margin.axisLeft, firstBottomWidth / 2)
7056
7164
  }
7057
7165
  else if (((this.options.data.bottom && this.options.data.bottom.rotate) || 0) > 0 && this.options.axis.hideBottom !== true) {
7058
7166
  this.options.margin.axisRight = Math.max(this.options.margin.axisRight, longestBottomBounds.width)
@@ -7082,6 +7190,23 @@ else {
7082
7190
  // Define the plot size
7083
7191
  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
7084
7192
  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
7193
+ if (this.options.orientation === 'vertical') {
7194
+ if (this.options.maxBandWidth) {
7195
+ this.plotWidth = Math.min(this.plotWidth, (this.options.data.bottom.data || []).length * this.options.maxBandWidth)
7196
+ }
7197
+ // some if to check if brushing is needed
7198
+ if (this.plotWidth / this.options.data.bottom.data.length < this.options.minBandWidth) {
7199
+ this.brushNeeded = true
7200
+ this.plotHeight -= this.options.brushHeight
7201
+ }
7202
+ }
7203
+ else {
7204
+ // some if to check if brushing is needed
7205
+ if (this.plotHeight / this.options.data.left.data.length < this.options.minBandWidth) {
7206
+ this.brushNeeded = true
7207
+ this.plotWidth -= this.options.brushHeight
7208
+ }
7209
+ }
7085
7210
  // Translate the layers
7086
7211
  this.leftAxisLayer
7087
7212
  .attr('transform', `translate(${this.options.margin.left + this.options.margin.axisLeft}, ${this.options.margin.top + this.options.margin.axisTop})`)
@@ -7114,6 +7239,12 @@ else {
7114
7239
  .attr('transform', `translate(${this.options.margin.left + this.options.margin.axisLeft}, ${this.options.margin.top + this.options.margin.axisTop})`)
7115
7240
  this.trackingLineLayer
7116
7241
  .attr('transform', `translate(${this.options.margin.left + this.options.margin.axisLeft}, ${this.options.margin.top + this.options.margin.axisTop})`)
7242
+ this.brushLayer
7243
+ .attr('transform', `translate(${this.options.margin.left + this.options.margin.axisLeft}, ${this.options.margin.top + this.options.margin.axisTop + this.plotHeight + longestBottomBounds.height})`)
7244
+ this.brushClip
7245
+ .attr('transform', `translate(${this.options.margin.left + this.options.margin.axisLeft}, ${this.options.margin.top + this.options.margin.axisTop + this.plotHeight + longestBottomBounds.height})`)
7246
+ .attr('width', this.plotWidth)
7247
+ .attr('height', this.options.brushHeight)
7117
7248
  this.eventLayer
7118
7249
  .attr('transform', `translate(${this.options.margin.left + this.options.margin.axisLeft}, ${this.options.margin.top + this.options.margin.axisTop})`)
7119
7250
  let that = this
@@ -7125,16 +7256,110 @@ else {
7125
7256
  .attr('fill-opacity', '0')
7126
7257
  // this.tooltip.transform(this.options.margin.left + this.options.margin.axisLeft, this.options.margin.top + this.options.margin.axisTop)
7127
7258
  // Configure the bottom axis
7128
- let bottomDomain = this.createDomain('bottom')
7259
+ let bottomDomain = this.createDomain('bottom')
7260
+ let bottomBrushDomain = this.createDomain('bottom', true)
7129
7261
  this.bottomAxis = d3[`scale${this.options.data.bottom.scale || 'Band'}`]()
7130
7262
  .domain(bottomDomain)
7131
- .range([0, this.plotWidth])
7263
+ .range([0, this.plotWidth])
7264
+ if (!this.brushInitialized) {
7265
+ this.bottomBrushAxis = d3[`scale${this.options.data.bottom.scale || 'Band'}`]()
7266
+ .domain(bottomBrushDomain)
7267
+ .range([0, this.plotWidth])
7268
+ }
7132
7269
  if (this.bottomAxis.nice) {
7133
7270
  // this.bottomAxis.nice()
7134
7271
  }
7135
7272
  if (this.bottomAxis.padding && this.options.data.bottom.padding) {
7136
7273
  this.bottomAxis.padding(this.options.data.bottom.padding || 0)
7137
7274
  }
7275
+ // BRUSH
7276
+ let brushMethod = `brushX`
7277
+ let brushLength = this.plotWidth
7278
+ let brushEnd = this.plotWidth
7279
+ let brushThickness = this.options.brushHeight
7280
+ if (this.options.orientation === 'horizontal') {
7281
+ brushMethod = 'brushY'
7282
+ brushLength = this.options.brushHeight
7283
+ brushThickness = this.plotHeight
7284
+ }
7285
+ else {
7286
+ if (brushLength / bottomDomain.length < this.options.minBandWidth) {
7287
+ brushEnd = this.plotWidth * ((this.plotWidth / this.options.minBandWidth) / bottomDomain.length)
7288
+ }
7289
+ }
7290
+ this.brush = d3[brushMethod]()
7291
+ .extent([
7292
+ [0, 0],
7293
+ [brushLength, brushThickness]
7294
+ ])
7295
+ .on('brush end', this.brushed)
7296
+ const brushResizePath = d => {
7297
+ let e = +(d.type === 'e')
7298
+ let x = e ? 1 : -1
7299
+ let y = this.options.brushHeight
7300
+ return (
7301
+ 'M' +
7302
+ 0.5 * x +
7303
+ ',' +
7304
+ y +
7305
+ 'A6,6 0 0 ' +
7306
+ e +
7307
+ ' ' +
7308
+ 6.5 * x +
7309
+ ',' +
7310
+ (y + 6) +
7311
+ 'V' +
7312
+ (2 * y - 6) +
7313
+ 'A6,6 0 0 ' +
7314
+ e +
7315
+ ' ' +
7316
+ 0.5 * x +
7317
+ ',' +
7318
+ 2 * y +
7319
+ 'Z' +
7320
+ 'M' +
7321
+ 2.5 * x +
7322
+ ',' +
7323
+ (y + 8) +
7324
+ 'V' +
7325
+ (2 * y - 8) +
7326
+ 'M' +
7327
+ 4.5 * x +
7328
+ ',' +
7329
+ (y + 8) +
7330
+ 'V' +
7331
+ (2 * y - 8)
7332
+ )
7333
+ }
7334
+ this.brushHandle = this.brushLayer
7335
+ .select('.brush')
7336
+ .selectAll('.handle--custom')
7337
+ .remove()
7338
+ this.brushHandle = this.brushLayer
7339
+ .select('.brush')
7340
+ .selectAll('.handle--custom')
7341
+ .data([{ type: 'w' }, { type: 'e' }])
7342
+ .enter()
7343
+ .append('path')
7344
+ .attr('class', 'handle--custom')
7345
+ .attr('stroke', 'transparent')
7346
+ .attr('fill', 'transparent')
7347
+ .attr('cursor', 'ew-resize')
7348
+ .attr('d', brushResizePath)
7349
+ // BRUSH END
7350
+ // this.brushArea.selectAll('*').remove()
7351
+ if (this.brushNeeded) {
7352
+ if (!this.brushInitialized) {
7353
+ this.brushInitialized = true
7354
+ this.brushLayer
7355
+ .select('.brush')
7356
+ .call(this.brush)
7357
+ .call(this.brush.move, [0, brushEnd])
7358
+ }
7359
+ }
7360
+ else {
7361
+ this.brushLayer.selectAll().remove()
7362
+ }
7138
7363
  if (this.options.margin.axisBottom > 0) {
7139
7364
  let timeFormatPattern = ''
7140
7365
  let tickDefinition
@@ -7195,15 +7420,12 @@ else {
7195
7420
  tickDefinition = this.options.data.bottom.ticks || 5
7196
7421
  }
7197
7422
  this.options.calculatedTimeFormatPattern = timeFormatPattern
7198
- let bAxisFunc = d3.axisBottom(this.bottomAxis)
7199
- // .ticks(this.options.data.bottom.ticks || Math.min(this.options.data.bottom.data.length, 5))
7200
- .ticks(tickDefinition)
7201
- // console.log('tickDefinition', tickDefinition)
7202
- // console.log(bAxisFunc)
7423
+ this.bAxisFunc = d3.axisBottom(this.bottomAxis)
7424
+ .ticks(tickDefinition)
7203
7425
  if (this.options.data.bottom.formatter) {
7204
- bAxisFunc.tickFormat(d => this.options.data.bottom.formatter(d))
7426
+ this.bAxisFunc.tickFormat(d => this.options.data.bottom.formatter(d))
7205
7427
  }
7206
- this.bottomAxisLayer.call(bAxisFunc)
7428
+ this.bottomAxisLayer.call(this.bAxisFunc)
7207
7429
  // console.log(this.bottomAxisLayer.ticks)
7208
7430
  if (this.options.data.bottom.rotate) {
7209
7431
  this.bottomAxisLayer.selectAll('text')
@@ -7213,11 +7435,15 @@ else {
7213
7435
  }
7214
7436
  }
7215
7437
  // Configure the left axis
7216
- let leftDomain = this.createDomain('left')
7438
+ let leftDomain = this.createDomain('left')
7439
+ let leftBrushDomain = this.createDomain('left', true)
7217
7440
  let rightDomain = this.createDomain('right')
7218
7441
  this.leftAxis = d3[`scale${this.options.data.left.scale || 'Linear'}`]()
7219
7442
  .domain(leftDomain)
7220
7443
  .range([this.plotHeight, 0])
7444
+ this.leftBrushAxis = d3[`scale${this.options.data.left.scale || 'Linear'}`]()
7445
+ .domain(leftBrushDomain)
7446
+ .range([this.options.brushHeight, 0])
7221
7447
  if (this.leftAxis.padding && this.options.data.left.padding) {
7222
7448
  this.leftAxis.padding(this.options.data.left.padding || 0)
7223
7449
  }
@@ -7286,7 +7512,7 @@ else {
7286
7512
  if (this.options.margin.axisRight > 0 && (this.options.data.right.min !== 0 || this.options.data.right.max !== 0)) {
7287
7513
  this.rightAxisLayer.call(
7288
7514
  d3.axisRight(this.rightAxis)
7289
- .ticks(this.options.data.left.ticks || 5)
7515
+ .ticks(this.options.data.right.ticks || 5)
7290
7516
  .tickFormat(d => {
7291
7517
  if (this.options.data.right.formatter) {
7292
7518
  d = this.options.data.right.formatter(d)
@@ -7333,25 +7559,29 @@ else {
7333
7559
  this[`remove${this.renderedKeys[key]}`](key)
7334
7560
  }
7335
7561
  }
7336
- // Draw the series data
7337
- this.renderedKeys = {}
7338
- this.options.data.series.forEach((series, index) => {
7339
- if (!series.key) {
7340
- series.key = this.createIdentity()
7341
- }
7342
- if (!series.color) {
7343
- series.color = this.options.colors[index % this.options.colors.length]
7344
- }
7345
- this[`render${series.type || 'bar'}`](series, index)
7346
- this.renderLabels(series, index)
7347
- this.renderedKeys[series.key] = series.type
7348
- })
7349
- if (this.options.refLines && this.options.refLines.length > 0) {
7350
- this.options.refLines.forEach(l => this.renderRefLine(l))
7351
- }
7562
+ this.renderComponents()
7352
7563
  }
7353
7564
  }
7354
7565
 
7566
+ }
7567
+ renderComponents () {
7568
+ // Draw the series data
7569
+ this.renderedKeys = {}
7570
+ this.options.data.series.forEach((series, index) => {
7571
+ if (!series.key) {
7572
+ series.key = this.createIdentity()
7573
+ }
7574
+ if (!series.color) {
7575
+ series.color = this.options.colors[index % this.options.colors.length]
7576
+ }
7577
+ this[`render${series.type || 'bar'}`](series, index)
7578
+ this.renderLabels(series, index)
7579
+ this.renderedKeys[series.key] = series.type
7580
+ })
7581
+ if (this.options.refLines && this.options.refLines.length > 0) {
7582
+ this.options.refLines.forEach(l => this.renderRefLine(l))
7583
+ }
7584
+
7355
7585
  }
7356
7586
  renderarea (series, index) {
7357
7587
  /* global d3 series index */
@@ -7410,74 +7640,111 @@ areas.enter().append('path')
7410
7640
  let xAxis = 'bottom'
7411
7641
  let yAxis = 'left'
7412
7642
  let bars = this.barLayer.selectAll(`.bar_${series.key}`).data(series.data)
7643
+ let brushBars = this.brushArea.selectAll(`.bar_${series.key}`).data(series.data)
7413
7644
  let acummulativeY = new Array(this.options.data.series.length).fill(0)
7414
7645
  if (this.options.orientation === 'horizontal') {
7415
7646
  xAxis = 'left'
7416
7647
  yAxis = 'bottom'
7417
7648
  }
7418
- let barWidth = this[`${xAxis}Axis`].bandwidth()
7419
- let groupedBarWidth = (barWidth - 10) / this.options.data.series.length
7420
7649
  // if (this.options.data.series.length > 1 && this.options.grouping === 'grouped') {
7421
7650
  // barWidth = barWidth / this.options.data.series.length - 4
7422
7651
  // }
7423
- function getBarHeight (d, i) {
7652
+ function getBarHeight (d, i, heightBounds, yAxis, xAxis) {
7653
+ let barWidth = this[`${xAxis}Axis`].bandwidth()
7654
+ let groupedBarWidth = (barWidth - 10) / this.options.data.series.length
7655
+ let output
7424
7656
  if (this.options.orientation === 'horizontal') {
7425
- return barWidth
7657
+ output = barWidth
7426
7658
  }
7427
7659
  else {
7428
- return this[`${yAxis}Axis`](d.y.value)
7660
+ if (!getBarX.call(this, d, i, xAxis)) {
7661
+ return null
7662
+ }
7663
+ output = (this[`${yAxis}Axis`](0)) - this[`${yAxis}Axis`](Math.abs(d.y.value))
7664
+ }
7665
+ if (isNaN(output)) {
7666
+ return null
7429
7667
  }
7668
+ return output
7430
7669
  }
7431
- function getBarWidth (d, i) {
7670
+ function getBarWidth (d, i, xAxis) {
7671
+ let barWidth = this[`${xAxis}Axis`].bandwidth()
7672
+ let groupedBarWidth = (barWidth - (xAxis.indexOf('Brush') === -1 ? 10 : 2)) / this.options.data.series.length
7673
+ let output
7432
7674
  if (this.options.orientation === 'horizontal') {
7433
7675
  let width = this[`${yAxis}Axis`](d.y.value)
7434
7676
  acummulativeY[d.y.index] += width
7435
- return width
7677
+ output = Math.max(1, width)
7436
7678
  }
7437
7679
  else {
7680
+ if (!getBarX.call(this, d, i, xAxis)) {
7681
+ return null
7682
+ }
7438
7683
  if (this.options.grouping === 'grouped') {
7439
- return groupedBarWidth
7684
+ output = Math.max(1, groupedBarWidth)
7685
+ }
7686
+ else {
7687
+ output = Math.max(1, barWidth)
7440
7688
  }
7441
- return barWidth
7442
7689
  }
7690
+ if (isNaN(output)) {
7691
+ return 0
7692
+ }
7693
+ return output
7443
7694
  }
7444
- function getBarX (d, i) {
7695
+ function getBarX (d, i, xAxis) {
7696
+ let barWidth = this[`${xAxis}Axis`].bandwidth()
7697
+ let groupedBarWidth = (barWidth - (xAxis.indexOf('Brush') === -1 ? 10 : 2)) / this.options.data.series.length
7698
+ let output
7445
7699
  if (this.options.orientation === 'horizontal') {
7446
7700
  if (this.options.grouping === 'stacked') {
7447
- return this[`${yAxis}Axis`](d.y.accumulative)
7701
+ output = this[`${yAxis}Axis`](d.y.accumulative)
7448
7702
  }
7449
7703
  else {
7450
- return 0
7704
+ output = 0
7451
7705
  }
7452
7706
  }
7453
7707
  else {
7454
- let adjustment = this.options.data[xAxis].scale === 'Time' ? 0 : this[`${xAxis}Axis`].bandwidth() / 2
7708
+ let adjustment = this.options.data[xAxis.replace('Brush', '')].scale === 'Time' ? 0 : this[`${xAxis}Axis`].bandwidth() / 2
7455
7709
  if (this.options.grouping === 'grouped') {
7456
- let barAdjustment = groupedBarWidth * index + 5 // + (index > 0 ? 4 : 0)
7457
- return this[`${xAxis}Axis`](this.parseX(d.x.value)) + barAdjustment
7710
+ let barAdjustment = groupedBarWidth * index + (xAxis.indexOf('Brush') === -1 ? 5 : 1) // + (index > 0 ? 4 : 0)
7711
+ output = this[`${xAxis}Axis`](this.parseX(d.x.value)) + barAdjustment
7458
7712
  }
7459
7713
  else {
7460
- return this[`${xAxis}Axis`](this.parseX(d.x.value)) + (i * barWidth) + adjustment
7714
+ // output = this[`${xAxis}Axis`](this.parseX(d.x.value)) + (i * barWidth) + adjustment
7715
+ output = this[`${xAxis}Axis`](this.parseX(d.x.value)) // + (i * barWidth)
7461
7716
  }
7462
7717
  }
7718
+ if (isNaN(output)) {
7719
+ return null
7720
+ }
7721
+ return output
7463
7722
  }
7464
- function getBarY (d, i) {
7723
+ function getBarY (d, i, heightBounds, yAxis, xAxis) {
7724
+ let barWidth = this[`${xAxis}Axis`].bandwidth()
7725
+ let groupedBarWidth = (barWidth - 10) / this.options.data.series.length
7726
+ let output
7465
7727
  if (this.options.orientation === 'horizontal') {
7466
7728
  if (this.options.grouping !== 'grouped') {
7467
- return this[`${xAxis}Axis`](this.parseX(d.x.value))
7729
+ output = this[`${xAxis}Axis`](this.parseX(d.x.value))
7468
7730
  }
7469
7731
  else {
7470
- return this[`${xAxis}Axis`](this.parseX(d.x.value)) + ((d.y.index || i) * barWidth)
7732
+ output = this[`${xAxis}Axis`](this.parseX(d.x.value)) + ((d.y.index || i) * barWidth)
7471
7733
  }
7472
7734
  }
7473
7735
  else {
7474
7736
  if (this.options.grouping === 'stacked') {
7475
- return this[`${yAxis}Axis`](d.y.accumulative)
7737
+ output = heightBounds - this[`${yAxis}Axis`](d.y.accumulative)
7476
7738
  }
7477
7739
  else {
7478
- return this.plotHeight - getBarHeight.call(this, d, i)
7740
+ let h = getBarHeight.call(this, d, i, heightBounds, yAxis, xAxis)
7741
+ output = (this[`${yAxis}Axis`](0)) - (h * (d.y.value < 0 ? 0 : 1))
7479
7742
  }
7480
7743
  }
7744
+ if (isNaN(output)) {
7745
+ return null
7746
+ }
7747
+ return output
7481
7748
  }
7482
7749
  bars
7483
7750
  .exit()
@@ -7486,26 +7753,56 @@ bars
7486
7753
  .remove()
7487
7754
 
7488
7755
  bars
7489
- .attr('width', getBarWidth.bind(this))
7490
- .attr('height', getBarHeight.bind(this))
7491
- .attr('x', getBarX.bind(this))
7492
- .attr('y', getBarY.bind(this))
7493
- .transition(this.transition)
7756
+ .attr('width', (d, i) => getBarWidth.call(this, d, i, xAxis))
7757
+ .attr('height', (d, i) => getBarHeight.call(this, d, i, this.plotHeight, yAxis, xAxis))
7758
+ .attr('x', (d, i) => getBarX.call(this, d, i, xAxis))
7759
+ .attr('y', (d, i) => getBarY.call(this, d, i, this.plotHeight, yAxis, xAxis))
7760
+ // .transition(this.transition)
7494
7761
  .attr('fill', d => d.y.color || d.color || series.color)
7495
7762
 
7496
7763
  bars
7497
7764
  .enter()
7498
7765
  .append('rect')
7499
- .attr('width', getBarWidth.bind(this))
7500
- .attr('height', getBarHeight.bind(this))
7501
- .attr('x', getBarX.bind(this))
7502
- .attr('y', getBarY.bind(this))
7766
+ .attr('width', (d, i) => getBarWidth.call(this, d, i, xAxis))
7767
+ .attr('height', (d, i) => getBarHeight.call(this, d, i, this.plotHeight, yAxis, xAxis))
7768
+ .attr('x', (d, i) => getBarX.call(this, d, i, xAxis))
7769
+ .attr('y', (d, i) => getBarY.call(this, d, i, this.plotHeight, yAxis, xAxis))
7503
7770
  // .transition(this.transition)
7504
7771
  .attr('fill', d => d.y.color || d.color || series.color)
7505
7772
  .attr('class', d => {
7506
7773
  return `bar bar_${series.key}`
7507
7774
  })
7508
7775
 
7776
+ if (!this.brushBarsInitialized[series.key]) {
7777
+ this.brushBarsInitialized[series.key] = true
7778
+ brushBars
7779
+ .exit()
7780
+ .transition(this.transition)
7781
+ .style('fill-opacity', 1e-6)
7782
+ .remove()
7783
+
7784
+ brushBars
7785
+ .attr('width', (d, i) => getBarWidth.call(this, d, i, `${xAxis}Brush`))
7786
+ .attr('height', (d, i) => getBarHeight.call(this, d, i, this.options.brushHeight, `${yAxis}Brush`, `${xAxis}Brush`))
7787
+ .attr('x', (d, i) => getBarX.call(this, d, i, `${xAxis}Brush`))
7788
+ .attr('y', (d, i) => getBarY.call(this, d, i, this.options.brushHeight, `${yAxis}Brush`, `${xAxis}Brush`))
7789
+ // .transition(this.transition)
7790
+ .attr('fill', d => d.y.color || d.color || series.color)
7791
+
7792
+ brushBars
7793
+ .enter()
7794
+ .append('rect')
7795
+ .attr('width', (d, i) => getBarWidth.call(this, d, i, `${xAxis}Brush`))
7796
+ .attr('height', (d, i) => getBarHeight.call(this, d, i, this.options.brushHeight, `${yAxis}Brush`, `${xAxis}Brush`))
7797
+ .attr('x', (d, i) => getBarX.call(this, d, i, `${xAxis}Brush`))
7798
+ .attr('y', (d, i) => getBarY.call(this, d, i, this.options.brushHeight, `${yAxis}Brush`, `${xAxis}Brush`))
7799
+ // .transition(this.transition)
7800
+ .attr('fill', d => d.y.color || d.color || series.color)
7801
+ .attr('class', d => {
7802
+ return `bar bar_${series.key}`
7803
+ })
7804
+ }
7805
+
7509
7806
  }
7510
7807
  removebar (key) {
7511
7808
  /* global key d3 */
@@ -7895,6 +8192,44 @@ if (el) {
7895
8192
  }
7896
8193
 
7897
8194
  }
8195
+ hideError () {
8196
+ const el = document.getElementById(`${this.elementId}`)
8197
+ if (el) {
8198
+ el.classList.remove('has-error')
8199
+ }
8200
+ // const chartEl = document.getElementById(`${this.elementId}_chartContainer`)
8201
+ // chartEl.classList.remove('hidden')
8202
+ this.svg.classed('hidden', false)
8203
+ const containerEl = document.getElementById(`${this.elementId}_errorContainer`)
8204
+ if (containerEl) {
8205
+ containerEl.classList.remove('active')
8206
+ }
8207
+ }
8208
+ showError (options) {
8209
+ const el = document.getElementById(`${this.elementId}`)
8210
+ if (el) {
8211
+ el.classList.add('has-error')
8212
+ }
8213
+ // const chartEl = document.getElementById(`${this.elementId}_chartContainer`)
8214
+ // chartEl.classList.add('hidden')
8215
+ this.svg.classed('hidden', true)
8216
+ const containerEl = document.getElementById(`${this.elementId}_errorContainer`)
8217
+ if (containerEl) {
8218
+ containerEl.classList.add('active')
8219
+ }
8220
+ if (options.title) {
8221
+ const titleEl = document.getElementById(`${this.elementId}_errorTitle`)
8222
+ if (titleEl) {
8223
+ titleEl.innerHTML = options.title
8224
+ }
8225
+ }
8226
+ if (options.message) {
8227
+ const messageEl = document.getElementById(`${this.elementId}_errorMessage`)
8228
+ if (messageEl) {
8229
+ messageEl.innerHTML = options.message
8230
+ }
8231
+ }
8232
+ }
7898
8233
  }
7899
8234
 
7900
8235
  class WebsyLegend {