@websy/websy-designs 1.2.32 → 1.3.0

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.
@@ -6,11 +6,13 @@
6
6
  WebsyPubSub
7
7
  WebsyForm
8
8
  WebsyDatePicker
9
+ WebsyDragDrop
9
10
  WebsyDropdown
10
11
  WebsyRouter
11
12
  WebsyResultList
12
13
  WebsyTable
13
14
  WebsyTable2
15
+ WebsyTable3
14
16
  WebsyChart
15
17
  WebsyChartTooltip
16
18
  WebsyLegend
@@ -423,6 +425,7 @@ class WebsyDatePicker {
423
425
  if (typeof d === 'number') {
424
426
  d = new Date(d)
425
427
  }
428
+ // d.setTime(d.getTime() + d.getTimezoneOffset() * 60000)
426
429
  return new Date(d.setHours(0, 0, 0, 0))
427
430
  }
428
431
  handleClick (event) {
@@ -441,11 +444,7 @@ class WebsyDatePicker {
441
444
  this.updateRange(index)
442
445
  }
443
446
  else if (event.target.classList.contains('websy-dp-date')) {
444
- // if (event.target.classList.contains('websy-disabled-date')) {
445
- // return
446
- // }
447
- // const timestamp = event.target.id.split('_')[0]
448
- // this.selectDate(+timestamp)
447
+ //
449
448
  }
450
449
  else if (event.target.classList.contains('websy-dp-confirm')) {
451
450
  this.close(true)
@@ -474,7 +473,8 @@ class WebsyDatePicker {
474
473
  handleMouseDown (event) {
475
474
  if (this.shiftPressed === true && this.currentselection.length > 0) {
476
475
  this.mouseDownId = this.currentselection[this.currentselection.length - 1]
477
- this.selectDate(+event.target.id.split('_')[1])
476
+ let dateId = event.target.getAttribute('data-id')
477
+ this.selectDate(+dateId)
478
478
  }
479
479
  else {
480
480
  this.mouseDown = true
@@ -487,7 +487,7 @@ class WebsyDatePicker {
487
487
  this.currentselection = []
488
488
  this.customRangeSelected = false
489
489
  }
490
- this.mouseDownId = +event.target.id.split('_')[1]
490
+ this.mouseDownId = +event.target.getAttribute('data-id')
491
491
  this.selectDate(this.mouseDownId)
492
492
  }
493
493
  }
@@ -498,9 +498,10 @@ class WebsyDatePicker {
498
498
  if (event.target.classList.contains('websy-disabled-date')) {
499
499
  return
500
500
  }
501
- if (event.target.id.split('_')[1] !== this.mouseDownId) {
501
+ let dateId = +event.target.getAttribute('data-id')
502
+ if (dateId !== this.mouseDownId) {
502
503
  this.dragging = true
503
- this.selectDate(+event.target.id.split('_')[1])
504
+ this.selectDate(dateId)
504
505
  }
505
506
  }
506
507
  }
@@ -548,6 +549,7 @@ class WebsyDatePicker {
548
549
  let rangeEnd
549
550
  if (this.options.mode === 'date') {
550
551
  d = this.floorDate(new Date(this.selectedRangeDates[0].getTime() + (i * this.oneDay)))
552
+ d.setHours(0, 0, 0, 0)
551
553
  d = d.getTime()
552
554
  rangeStart = this.selectedRangeDates[0].getTime()
553
555
  rangeEnd = this.selectedRangeDates[this.selectedRangeDates.length - 1].getTime()
@@ -817,7 +819,7 @@ class WebsyDatePicker {
817
819
  }
818
820
  html += paddedDays.join('')
819
821
  }
820
- html += months[key].map(d => `<li id='${this.elementId}_${d.id}_date' class='websy-dp-date ${d.disabled === true ? 'websy-disabled-date' : ''}'>${d.dayOfMonth}</li>`).join('')
822
+ html += months[key].map(d => `<li id='${this.elementId}_${d.id}_date' data-id='${d.id}' class='websy-dp-date ${d.disabled === true ? 'websy-disabled-date' : ''}'>${d.dayOfMonth}</li>`).join('')
821
823
  html += `
822
824
  </ul>
823
825
  </div>
@@ -938,7 +940,7 @@ class WebsyDatePicker {
938
940
  selectRange (index, confirm = true) {
939
941
  if (this.options.ranges[this.options.mode][index]) {
940
942
  this.selectedRangeDates = [...this.options.ranges[this.options.mode][index].range]
941
- this.currentselection = [...this.options.ranges[this.options.mode][index].range]
943
+ this.currentselection = this.options.ranges[this.options.mode][index].range.map(d => d.getTime())
942
944
  this.selectedRange = +index
943
945
  const el = document.getElementById(`${this.elementId}_header`)
944
946
  if (el) {
@@ -1109,6 +1111,276 @@ Date.prototype.floor = function () {
1109
1111
  return new Date(`${this.getMonth() + 1}/${this.getDate()}/${this.getFullYear()}`)
1110
1112
  }
1111
1113
 
1114
+ /* global WebsyDesigns GlobalPubSub */
1115
+ class WebsyDragDrop {
1116
+ constructor (elementId, options) {
1117
+ const DEFAULTS = {
1118
+ items: [],
1119
+ orientation: 'horizontal',
1120
+ dropPlaceholder: 'Drop item here'
1121
+ }
1122
+ this.busy = false
1123
+ this.options = Object.assign({}, DEFAULTS, options)
1124
+ this.elementId = elementId
1125
+ if (!elementId) {
1126
+ console.log('No element Id provided for Websy DragDrop')
1127
+ return
1128
+ }
1129
+ const el = document.getElementById(elementId)
1130
+ if (el) {
1131
+ el.innerHTML = `
1132
+ <div id='${this.elementId}_container' class='websy-drag-drop-container ${this.options.orientation}'>
1133
+ <div>
1134
+ </div>
1135
+ `
1136
+ el.addEventListener('click', this.handleClick.bind(this))
1137
+ el.addEventListener('dragstart', this.handleDragStart.bind(this))
1138
+ el.addEventListener('dragover', this.handleDragOver.bind(this))
1139
+ el.addEventListener('dragleave', this.handleDragLeave.bind(this))
1140
+ el.addEventListener('drop', this.handleDrop.bind(this))
1141
+ window.addEventListener('dragend', this.handleDragEnd.bind(this))
1142
+ }
1143
+ else {
1144
+ console.error(`No element found with ID ${this.elementId}`)
1145
+ }
1146
+ GlobalPubSub.subscribe(this.elementId, 'requestForDDItem', this.handleRequestForItem.bind(this))
1147
+ GlobalPubSub.subscribe(this.elementId, 'add', this.addItem.bind(this))
1148
+ this.render()
1149
+ }
1150
+ addItem (data) {
1151
+ if (data.target === this.elementId && this.busy === false) {
1152
+ this.busy = true
1153
+ console.log('adding item to dd')
1154
+ // check that an item with the same id doesn't already exist
1155
+ let index = this.getItemIndex(data.item.id)
1156
+ if (index === -1) {
1157
+ this.options.items.splice(data.index, 0, data.item)
1158
+ const startEl = document.getElementById(`${this.elementId}start_item`)
1159
+ if (startEl) {
1160
+ if (this.options.items.length === 0) {
1161
+ startEl.classList.add('empty')
1162
+ }
1163
+ else {
1164
+ startEl.classList.remove('empty')
1165
+ }
1166
+ }
1167
+ if (this.options.onItemAdded) {
1168
+ this.options.onItemAdded()
1169
+ }
1170
+ }
1171
+ this.busy = false
1172
+ }
1173
+ }
1174
+ createItemHtml (elementId, index, item) {
1175
+ if (!item.id) {
1176
+ item.id = WebsyDesigns.Utils.createIdentity()
1177
+ }
1178
+ let html = `
1179
+ <div id='${item.id}_item' class='websy-dragdrop-item' draggable='true' data-id='${item.id}'>
1180
+ <div id='${item.id}_itemInner' class='websy-dragdrop-item-inner' data-id='${item.id}'>
1181
+ `
1182
+ if (item.component) {
1183
+ html += `<div id='${item.id}_component'></div>`
1184
+ }
1185
+ else {
1186
+ html += `${item.html || item.label || ''}`
1187
+ }
1188
+ html += `
1189
+ </div>
1190
+ <div id='${item.id}_dropZone' class='websy-drop-zone droppable' data-index='${item.id}' data-side='right' data-id='${item.id}' data-placeholder='${this.options.dropPlaceholder}'></div>
1191
+ </div>
1192
+ `
1193
+ return html
1194
+ }
1195
+ getItemIndex (id) {
1196
+ for (let i = 0; i < this.options.items.length; i++) {
1197
+ if (this.options.items[i].id === id) {
1198
+ return i
1199
+ }
1200
+ }
1201
+ return -1
1202
+ }
1203
+ handleClick (event) {
1204
+
1205
+ }
1206
+ handleDragStart (event) {
1207
+ this.draggedId = event.target.getAttribute('data-id')
1208
+ event.dataTransfer.effectAllowed = 'move'
1209
+ event.dataTransfer.setData('application/wd-item', JSON.stringify({el: event.target.id, id: this.elementId, itemId: this.draggedId}))
1210
+ // console.log('drag start', event)
1211
+ event.target.style.opacity = 0.5
1212
+ this.dragging = true
1213
+ }
1214
+ handleDragOver (event) {
1215
+ // console.log('drag over', event.target.classList)
1216
+ if (event.preventDefault) {
1217
+ event.preventDefault()
1218
+ }
1219
+ if (!event.target.classList.contains('droppable')) {
1220
+ return
1221
+ }
1222
+ event.target.classList.add('drag-over')
1223
+ }
1224
+ handleDragLeave (event) {
1225
+ // console.log('drag leave', event.target.classList)
1226
+ if (!event.target.classList.contains('droppable')) {
1227
+ return
1228
+ }
1229
+ event.target.classList.remove('drag-over')
1230
+ // let side = event.target.getAttribute('data-side')
1231
+ // let id = event.target.getAttribute('data-id')
1232
+ // let droppedItem = this.options.items[id]
1233
+ // this.removeExpandedDrop(side, id, droppedItem)
1234
+ }
1235
+ handleDrop (event) {
1236
+ // console.log('drag drop')
1237
+ // console.log(event.dataTransfer.getData('application/wd-item'))
1238
+ const data = JSON.parse(event.dataTransfer.getData('application/wd-item'))
1239
+ if (event.preventDefault) {
1240
+ event.preventDefault()
1241
+ }
1242
+ if (!event.target.classList.contains('droppable')) {
1243
+ return
1244
+ }
1245
+ let side = event.target.getAttribute('data-side')
1246
+ let id = event.target.getAttribute('data-id')
1247
+ let index = this.getItemIndex(id)
1248
+ let draggedIndex = this.getItemIndex(data.id)
1249
+ let droppedItem = this.options.items[index]
1250
+ if (side === 'right') {
1251
+ index += 1
1252
+ }
1253
+ if (draggedIndex === -1) {
1254
+ // console.log('requestForDDItem')
1255
+ GlobalPubSub.publish(data.id, 'requestForDDItem', {
1256
+ group: this.options.group,
1257
+ source: data.id,
1258
+ target: this.elementId,
1259
+ index,
1260
+ id: data.itemId
1261
+ })
1262
+ }
1263
+ else if (index > draggedIndex) {
1264
+ // insert and then remove
1265
+ this.options.items.splice(index, 0, droppedItem)
1266
+ this.options.items.splice(draggedIndex, 1)
1267
+ if (this.options.onOrderUpdated) {
1268
+ this.options.onOrderUpdated()
1269
+ }
1270
+ }
1271
+ else {
1272
+ // remove and then insert
1273
+ this.options.items.splice(draggedIndex, 1)
1274
+ this.options.items.splice(index, 0, droppedItem)
1275
+ if (this.options.onOrderUpdated) {
1276
+ this.options.onOrderUpdated()
1277
+ }
1278
+ }
1279
+ // this.removeExpandedDrop(side, id, droppedItem)
1280
+ // const draggedEl = document.getElementById(`${this.elementId}_${this.draggedId}_item`)
1281
+ const draggedEl = document.getElementById(data.el)
1282
+ const droppedEl = document.getElementById(`${id}_item`)
1283
+ if (draggedEl) {
1284
+ droppedEl.insertAdjacentElement('afterend', draggedEl)
1285
+ }
1286
+ let dragOverEl = droppedEl.querySelector('.drag-over')
1287
+ if (dragOverEl) {
1288
+ dragOverEl.classList.remove('drag-over')
1289
+ }
1290
+ }
1291
+ handleDragEnd (event) {
1292
+ // console.log('drag end')
1293
+ event.target.style.opacity = 1
1294
+ this.draggedId = null
1295
+ this.dragging = false
1296
+ const startEl = document.getElementById(`${this.elementId}start_item`)
1297
+ if (startEl) {
1298
+ if (this.options.items.length === 0) {
1299
+ startEl.classList.add('empty')
1300
+ }
1301
+ else {
1302
+ startEl.classList.remove('empty')
1303
+ }
1304
+ }
1305
+ }
1306
+ handleRequestForItem (data) {
1307
+ if (data.group === this.options.group) {
1308
+ let index = this.getItemIndex(data.id)
1309
+ if (index !== -1) {
1310
+ let itemToAdd = this.options.items.splice(index, 1)
1311
+ GlobalPubSub.publish(data.target, 'add', {
1312
+ target: data.target,
1313
+ index: data.index,
1314
+ item: itemToAdd[0]
1315
+ })
1316
+ }
1317
+ }
1318
+ }
1319
+ measureItems () {
1320
+ const el = document.getElementById(`${this.elementId}_container`)
1321
+ this.options.items.forEach(d => {
1322
+
1323
+ })
1324
+ }
1325
+ // removeExpandedDrop (side, id, droppedItem) {
1326
+ // let dropEl
1327
+ // const dropImageEl = document.getElementById(`${id}_itemInner`)
1328
+ // // const placeholderEl = document.getElementById(`${this.elementId}_${id}_dropZonePlaceholder`)
1329
+ // if (side === 'left') {
1330
+ // dropEl = document.getElementById(`${this.elementId}_${id}_dropZoneLeft`)
1331
+ // dropImageEl.style.left = `0px`
1332
+ // }
1333
+ // else if (side === 'right') {
1334
+ // dropEl = document.getElementById(`${this.elementId}_${id}_dropZoneRight`)
1335
+ // }
1336
+ // else {
1337
+ // dropEl = document.getElementById(`${this.elementId}_${id}_dropZoneEnd`)
1338
+ // }
1339
+ // if (dropEl) {
1340
+ // const dropElSize = dropEl.getBoundingClientRect()
1341
+ // dropEl.style.width = `${(dropElSize.width / 2)}px`
1342
+ // dropEl.style.marginLeft = null
1343
+ // dropEl.style.border = null
1344
+ // }
1345
+ // if (placeholderEl) {
1346
+ // placeholderEl.classList.remove('active')
1347
+ // placeholderEl.style.left = null
1348
+ // placeholderEl.style.right = null
1349
+ // placeholderEl.style.width = null
1350
+ // placeholderEl.style.height = null
1351
+ // }
1352
+ // }
1353
+ removeItem (id) {
1354
+
1355
+ }
1356
+ render () {
1357
+ const el = document.getElementById(`${this.elementId}_container`)
1358
+ if (el) {
1359
+ this.measureItems()
1360
+ let html = `
1361
+ <div id='${this.elementId}start_item' class='websy-dragdrop-item ${this.options.items.length === 0 ? 'empty' : ''}' data-id='${this.elementId}start'>
1362
+ <div id='${this.elementId}start_dropZone' class='websy-drop-zone droppable' data-index='start' data-side='start' data-id='${this.elementId}start' data-placeholder='${this.options.dropPlaceholder}'></div>
1363
+ </div>
1364
+ `
1365
+ html += this.options.items.map((d, i) => this.createItemHtml(this.elementId, i, d)).join('')
1366
+ el.innerHTML = html
1367
+ this.options.items.forEach((item, i) => {
1368
+ if (item.component) {
1369
+ if (item.isQlikPlugin && WebsyDesigns.QlikPlugin[item.component]) {
1370
+ item.instance = new WebsyDesigns.QlikPlugin[item.component](`${item.id}_component`, item.options)
1371
+ }
1372
+ else if (WebsyDesigns[item.component]) {
1373
+ item.instance = new WebsyDesigns[item.component](`${item.id}_component`, item.options)
1374
+ }
1375
+ else {
1376
+ console.error(`Component ${item.component} not found.`)
1377
+ }
1378
+ }
1379
+ })
1380
+ }
1381
+ }
1382
+ }
1383
+
1112
1384
  /* global WebsyUtils */
1113
1385
  class WebsyDropdown {
1114
1386
  constructor (elementId, options) {
@@ -1223,18 +1495,25 @@ class WebsyDropdown {
1223
1495
  if (typeof d.index === 'undefined') {
1224
1496
  d.index = i
1225
1497
  }
1498
+ d.currentIndex = i
1226
1499
  return d
1227
- })
1228
- const el = document.getElementById(`${this.elementId}_items`)
1229
- if (el.childElementCount === 0) {
1230
- this.render()
1500
+ })
1501
+ const headerEl = document.getElementById(`${this.elementId}_header`)
1502
+ if (headerEl) {
1503
+ headerEl.classList[`${this.options.allowClear === true ? 'add' : 'remove'}`]('allow-clear')
1231
1504
  }
1232
- else {
1233
- if (this.options.items.length === 0) {
1234
- this.options.items = [{label: this.options.noItemsText || 'No Items'}]
1505
+ const el = document.getElementById(`${this.elementId}_items`)
1506
+ if (el) {
1507
+ if (el.childElementCount === 0) {
1508
+ this.render()
1235
1509
  }
1236
- this.renderItems()
1237
- }
1510
+ else {
1511
+ if (this.options.items.length === 0) {
1512
+ this.options.items = [{label: this.options.noItemsText || 'No Items'}]
1513
+ }
1514
+ this.renderItems()
1515
+ }
1516
+ }
1238
1517
  }
1239
1518
  get data () {
1240
1519
  return this.options.items
@@ -1475,6 +1754,10 @@ class WebsyDropdown {
1475
1754
  const labelEl = document.getElementById(`${this.elementId}_selectedItems`)
1476
1755
  const inputEl = document.getElementById(`${this.elementId}_input`)
1477
1756
  const itemEls = el.querySelectorAll(`.websy-dropdown-item`)
1757
+ let dataToUse = this._originalData
1758
+ if (this.options.onSearch) {
1759
+ dataToUse = this.options.items
1760
+ }
1478
1761
  for (let i = 0; i < itemEls.length; i++) {
1479
1762
  itemEls[i].classList.remove('active')
1480
1763
  let index = itemEls[i].getAttribute('data-index')
@@ -1510,14 +1793,14 @@ class WebsyDropdown {
1510
1793
  }
1511
1794
  else if (this.selectedItems.length > 1) {
1512
1795
  if (this.options.showCompleteSelectedList === true) {
1513
- let selectedLabels = this.selectedItems.map(s => this.options.items[s].label || this.options.items[s].value).join(this.options.multiValueDelimiter)
1514
- let selectedValues = this.selectedItems.map(s => this.options.items[s].value || this.options.items[s].label).join(this.options.multiValueDelimiter)
1796
+ let selectedLabels = this.selectedItems.map(s => dataToUse[s].label || dataToUse[s].value).join(this.options.multiValueDelimiter)
1797
+ let selectedValues = this.selectedItems.map(s => dataToUse[s].value || dataToUse[s].label).join(this.options.multiValueDelimiter)
1515
1798
  labelEl.innerHTML = selectedLabels
1516
1799
  labelEl.setAttribute('data-info', selectedLabels)
1517
1800
  inputEl.value = selectedValues
1518
1801
  }
1519
1802
  else {
1520
- let selectedValues = this.selectedItems.map(s => this.options.items[s].value || this.options.items[s].label).join(this.options.multiValueDelimiter)
1803
+ let selectedValues = this.selectedItems.map(s => dataToUse[s].value || dataToUse[s].label).join(this.options.multiValueDelimiter)
1521
1804
  labelEl.innerHTML = `${this.selectedItems.length} selected`
1522
1805
  labelEl.setAttribute('data-info', '')
1523
1806
  inputEl.value = selectedValues
@@ -1531,6 +1814,10 @@ class WebsyDropdown {
1531
1814
  }
1532
1815
  }
1533
1816
  updateSelected (index) {
1817
+ let dataToUse = this._originalData && this._originalData.length > 0 ? this._originalData : this.options.items
1818
+ if (this.options.onSearch) {
1819
+ dataToUse = this.options.items
1820
+ }
1534
1821
  if (typeof index !== 'undefined' && index !== null) {
1535
1822
  let pos = this.selectedItems.indexOf(index)
1536
1823
  if (this.options.multiSelect === false) {
@@ -1545,10 +1832,11 @@ class WebsyDropdown {
1545
1832
  }
1546
1833
  }
1547
1834
  }
1548
- const item = this.options.items[index]
1835
+ // const item = this.options.items[index]
1836
+ const item = dataToUse[index]
1549
1837
  this.updateHeader(item)
1550
1838
  if (item && this.options.onItemSelected) {
1551
- this.options.onItemSelected(item, this.selectedItems, this.options.items, this.options)
1839
+ this.options.onItemSelected(item, this.selectedItems, dataToUse, this.options)
1552
1840
  }
1553
1841
  if (this.options.closeAfterSelection === true) {
1554
1842
  this.close()
@@ -2469,18 +2757,35 @@ class WebsyPubSub {
2469
2757
  this.elementId = elementId
2470
2758
  this.subscriptions = {}
2471
2759
  }
2472
- publish (method, data) {
2473
- if (this.subscriptions[method]) {
2474
- this.subscriptions[method].forEach(fn => {
2475
- fn(data)
2476
- })
2760
+ publish (id, method, data) {
2761
+ if (arguments.length === 3) {
2762
+ if (this.subscriptions[id] && this.subscriptions[id][method]) {
2763
+ this.subscriptions[id][method](data)
2764
+ }
2765
+ }
2766
+ else {
2767
+ if (this.subscriptions[id]) {
2768
+ this.subscriptions[id].forEach(fn => {
2769
+ fn(method)
2770
+ })
2771
+ }
2477
2772
  }
2478
2773
  }
2479
- subscribe (method, fn) {
2480
- if (!this.subscriptions[method]) {
2481
- this.subscriptions[method] = []
2774
+ subscribe (id, method, fn) {
2775
+ if (arguments.length === 3) {
2776
+ if (!this.subscriptions[id]) {
2777
+ this.subscriptions[id] = {}
2778
+ }
2779
+ if (!this.subscriptions[id][method]) {
2780
+ this.subscriptions[id][method] = fn
2781
+ }
2782
+ }
2783
+ else {
2784
+ if (!this.subscriptions[id]) {
2785
+ this.subscriptions[id] = []
2786
+ }
2787
+ this.subscriptions[id].push(method)
2482
2788
  }
2483
- this.subscriptions[method].push(fn)
2484
2789
  }
2485
2790
  }
2486
2791
 
@@ -3701,6 +4006,7 @@ const WebsyUtils = {
3701
4006
  let red = 0
3702
4007
  let green = 0
3703
4008
  let blue = 0
4009
+ let alpha = 1
3704
4010
  if (backgroundColor.indexOf('#') !== -1) {
3705
4011
  // hex color
3706
4012
  backgroundColor = backgroundColor.replace('#', '')
@@ -3712,13 +4018,15 @@ const WebsyUtils = {
3712
4018
  }
3713
4019
  else if (backgroundColor.toLowerCase().indexOf('rgb') !== -1) {
3714
4020
  // rgb color
3715
- colorParts = backgroundColor.replace(/rgb\(/gi, '').replace(/\)/gi, '')
4021
+ colorParts = backgroundColor.replace(/rgba\(/gi, '').replace(/\)/gi, '')
4022
+ colorParts = colorParts.replace(/rgb\(/gi, '')
3716
4023
  colorParts = colorParts.split(',')
3717
4024
  red = colorParts[0]
3718
4025
  green = colorParts[1]
3719
4026
  blue = colorParts[2]
4027
+ alpha = colorParts[3] || 1
3720
4028
  }
3721
- return (red * 0.299 + green * 0.587 + blue * 0.114) > 186 ? darkColor : lightColor
4029
+ return ((red * 0.299 + green * 0.587 + blue * 0.114) / alpha) > 186 ? darkColor : lightColor
3722
4030
  },
3723
4031
  measureText (text, rotation = 0, fontSize = '12px') {
3724
4032
  if (!isNaN(fontSize)) {
@@ -4168,8 +4476,15 @@ class WebsyTable {
4168
4476
  }
4169
4477
  let headHTML = '<tr>' + this.options.columns.map((c, i) => {
4170
4478
  if (c.show !== false) {
4479
+ let style = ''
4480
+ if (c.style) {
4481
+ style += c.style
4482
+ }
4483
+ if (c.width) {
4484
+ style += `width: ${(c.width || 'auto')};`
4485
+ }
4171
4486
  return `
4172
- <th ${c.width ? 'style="width: ' + (c.width || 'auto') + ';"' : ''}>
4487
+ <th style="${style}">
4173
4488
  <div class ="tableHeader">
4174
4489
  <div class="leftSection">
4175
4490
  <div
@@ -4583,7 +4898,12 @@ class WebsyTable2 {
4583
4898
  }
4584
4899
  }
4585
4900
  hideLoading () {
4586
- this.loadingDialog.hide()
4901
+ if (this.options.onLoading) {
4902
+ this.options.onLoading(false)
4903
+ }
4904
+ else {
4905
+ this.loadingDialog.hide()
4906
+ }
4587
4907
  }
4588
4908
  internalSort (column, colIndex) {
4589
4909
  this.options.columns.forEach((c, i) => {
@@ -4658,7 +4978,8 @@ class WebsyTable2 {
4658
4978
  class="tableHeaderField ${['asc', 'desc'].indexOf(c.sort) !== -1 ? 'sortable-column' : ''}"
4659
4979
  data-sort-index="${c.sortIndex || i}"
4660
4980
  data-index="${i}"
4661
- data-sort="${c.sort}"
4981
+ data-sort="${c.sort}"
4982
+ style="${c.style || ''}"
4662
4983
  >
4663
4984
  ${c.name}
4664
4985
  </div>
@@ -4760,7 +5081,12 @@ class WebsyTable2 {
4760
5081
  }
4761
5082
  }
4762
5083
  showLoading (options) {
4763
- this.loadingDialog.show(options)
5084
+ if (this.options.onLoading) {
5085
+ this.options.onLoading(true)
5086
+ }
5087
+ else {
5088
+ this.loadingDialog.show(options)
5089
+ }
4764
5090
  }
4765
5091
  getColumnParameters (values) {
4766
5092
  const tableEl = document.getElementById(`${this.elementId}_table`)
@@ -4824,6 +5150,603 @@ class WebsyTable2 {
4824
5150
  }
4825
5151
  }
4826
5152
 
5153
+ /* global WebsyDesigns */
5154
+ class WebsyTable3 {
5155
+ constructor (elementId, options) {
5156
+ this.elementId = elementId
5157
+ const DEFAULTS = {
5158
+ virtualScroll: false,
5159
+ showTotalsAbove: true,
5160
+ minHandleSize: 20,
5161
+ maxColWidth: '50%',
5162
+ allowPivoting: false,
5163
+ searchIcon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 512 512"><title>ionicons-v5-f</title><path d="M221.09,64A157.09,157.09,0,1,0,378.18,221.09,157.1,157.1,0,0,0,221.09,64Z" style="fill:none;stroke:#000;stroke-miterlimit:10;stroke-width:32px"/><line x1="338.29" y1="338.29" x2="448" y2="448" style="fill:none;stroke:#000;stroke-linecap:round;stroke-miterlimit:10;stroke-width:32px"/></svg>`
5164
+ }
5165
+ this.options = Object.assign({}, DEFAULTS, options)
5166
+ this.sizes = {}
5167
+ this.scrollDragging = false
5168
+ this.cellDragging = false
5169
+ this.vScrollRequired = false
5170
+ this.hScrollRequired = false
5171
+ this.pinnedColumns = 0
5172
+ this.startRow = 0
5173
+ this.endRow = 0
5174
+ this.startCol = 0
5175
+ this.endCol = 0
5176
+ this.mouseYStart = 0
5177
+ this.mouseYStart = 0
5178
+ if (!elementId) {
5179
+ console.log('No element Id provided for Websy Table')
5180
+ return
5181
+ }
5182
+ const el = document.getElementById(this.elementId)
5183
+ if (el) {
5184
+ let html = `
5185
+ <div id='${this.elementId}_tableContainer' class='websy-vis-table-3 ${this.options.paging === 'pages' ? 'with-paging' : ''} ${this.options.virtualScroll === true ? 'with-virtual-scroll' : ''}'>
5186
+ <!--<div class="download-button">
5187
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M16 11h5l-9 10-9-10h5v-11h8v11zm1 11h-10v2h10v-2z"/></svg>
5188
+ </div>-->
5189
+ <div id="${this.elementId}_tableInner" class="websy-table-inner-container">
5190
+ <table id="${this.elementId}_tableHeader" class="websy-table-header"></table>
5191
+ <table id="${this.elementId}_tableBody" class="websy-table-body"></table>
5192
+ <table id="${this.elementId}_tableFooter" class="websy-table-footer"></table>
5193
+ <div id="${this.elementId}_vScrollContainer" class="websy-v-scroll-container">
5194
+ <div id="${this.elementId}_vScrollHandle" class="websy-scroll-handle websy-scroll-handle-y"></div>
5195
+ </div>
5196
+ <div id="${this.elementId}_hScrollContainer" class="websy-h-scroll-container">
5197
+ <div id="${this.elementId}_hScrollHandle" class="websy-scroll-handle websy-scroll-handle-x"></div>
5198
+ </div>
5199
+ </div>
5200
+ <div id="${this.elementId}_errorContainer" class='websy-vis-error-container'>
5201
+ <div>
5202
+ <div id="${this.elementId}_errorTitle"></div>
5203
+ <div id="${this.elementId}_errorMessage"></div>
5204
+ </div>
5205
+ </div>
5206
+ <div id="${this.elementId}_dropdownContainer"></div>
5207
+ <div id="${this.elementId}_loadingContainer"></div>
5208
+ </div>
5209
+ `
5210
+ if (this.options.paging === 'pages') {
5211
+ html += `
5212
+ <div class="websy-table-paging-container">
5213
+ Show <div id="${this.elementId}_pageSizeSelector" class="websy-vis-page-selector"></div> rows
5214
+ <ul id="${this.elementId}_pageList" class="websy-vis-page-list"></ul>
5215
+ </div>
5216
+ `
5217
+ }
5218
+ el.innerHTML = html
5219
+ el.addEventListener('click', this.handleClick.bind(this))
5220
+ el.addEventListener('mousedown', this.handleMouseDown.bind(this))
5221
+ window.addEventListener('mousemove', this.handleMouseMove.bind(this))
5222
+ window.addEventListener('mouseup', this.handleMouseUp.bind(this))
5223
+ let scrollEl = document.getElementById(`${this.elementId}_tableBody`)
5224
+ if (scrollEl) {
5225
+ scrollEl.addEventListener('wheel', this.handleScrollWheel.bind(this))
5226
+ }
5227
+ this.loadingDialog = new WebsyDesigns.LoadingDialog(`${this.elementId}_loadingContainer`)
5228
+ this.render(this.options.data)
5229
+ }
5230
+ else {
5231
+ console.error(`No element found with ID ${this.elementId}`)
5232
+ }
5233
+ }
5234
+ set columns (columns) {
5235
+ this.options.columns = columns
5236
+ this.renderColumnHeaders()
5237
+ }
5238
+ set totals (totals) {
5239
+ this.options.totals = totals
5240
+ this.renderTotals()
5241
+ }
5242
+ appendRows (data) {
5243
+ this.hideError()
5244
+ let bodyEl = document.getElementById(`${this.elementId}_tableBody`)
5245
+ if (bodyEl) {
5246
+ if (this.options.virtualScroll === true) {
5247
+ bodyEl.innerHTML = this.buildBodyHtml(data, true)
5248
+ }
5249
+ else {
5250
+ bodyEl.innerHTML += this.buildBodyHtml(data, true)
5251
+ }
5252
+ }
5253
+ // this.data = this.data.concat(data)
5254
+ // this.rowCount = this.data.length
5255
+ }
5256
+ buildBodyHtml (data = [], useWidths = false) {
5257
+ if (data.length === 0) {
5258
+ return ''
5259
+ }
5260
+ let bodyHtml = ``
5261
+ let sizingColumns = this.options.columns[this.options.columns.length - 1]
5262
+ if (useWidths === true) {
5263
+ bodyHtml += '<colgroup>'
5264
+ bodyHtml += sizingColumns.map(c => `
5265
+ <col
5266
+ style='width: ${c.width || c.actualWidth}px!important'
5267
+ ></col>
5268
+ `).join('')
5269
+ bodyHtml += '</colgroup>'
5270
+ }
5271
+ data.forEach(row => {
5272
+ bodyHtml += `<tr class="websy-table-row">`
5273
+ row.forEach((cell, cellIndex) => {
5274
+ let style = ''
5275
+ if (cell.style) {
5276
+ style += cell.style
5277
+ }
5278
+ if (cell.backgroundColor) {
5279
+ style += `background-color: ${cell.backgroundColor}; `
5280
+ if (!cell.color) {
5281
+ style += `color: ${WebsyDesigns.Utils.getLightDark(cell.backgroundColor)}; `
5282
+ }
5283
+ }
5284
+ if (cell.color) {
5285
+ style += `color: ${cell.color}; `
5286
+ }
5287
+ bodyHtml += `<td
5288
+ class='websy-table-cell'
5289
+ style='${style}'
5290
+ data-info='${cell.value}'
5291
+ colspan='${cell.colspan || 1}'
5292
+ rowspan='${cell.rowspan || 1}'
5293
+ `
5294
+ // if (useWidths === true) {
5295
+ // bodyHtml += `
5296
+ // style='width: ${sizingColumns[cellIndex].width || sizingColumns[cellIndex].actualWidth}px!important'
5297
+ // width='${sizingColumns[cellIndex].width || sizingColumns[cellIndex].actualWidth}'
5298
+ // `
5299
+ // }
5300
+ bodyHtml += `
5301
+ >
5302
+ ${cell.value}
5303
+ </td>`
5304
+ })
5305
+ bodyHtml += `</tr>`
5306
+ })
5307
+ // bodyHtml += `</div>`
5308
+ return bodyHtml
5309
+ }
5310
+ buildHeaderHtml (useWidths = false) {
5311
+ let headerHtml = ''
5312
+ let sizingColumns = this.options.columns[this.options.columns.length - 1]
5313
+ if (useWidths === true) {
5314
+ headerHtml += '<colgroup>'
5315
+ headerHtml += sizingColumns.map(c => `
5316
+ <col
5317
+ style='width: ${c.width || c.actualWidth}px!important'
5318
+ ></col>
5319
+ `).join('')
5320
+ headerHtml += '</colgroup>'
5321
+ }
5322
+ this.options.columns.forEach((row, rowIndex) => {
5323
+ if (useWidths === false && rowIndex !== this.options.columns.length - 1) {
5324
+ // if we're calculating the size we only want to render the last row of column headers
5325
+ return
5326
+ }
5327
+ headerHtml += `<tr class="websy-table-row websy-table-header-row">`
5328
+ row.forEach((col, colIndex) => {
5329
+ headerHtml += `<td
5330
+ class='websy-table-cell'
5331
+ style='${col.style}'
5332
+ colspan='${col.colspan || 1}'
5333
+ rowspan='${col.rowspan || 1}'
5334
+ `
5335
+ // if (useWidths === true && rowIndex === this.options.columns.length - 1) {
5336
+ // headerHtml += `
5337
+ // style='width: ${col.width || col.actualWidth}px'
5338
+ // width='${col.width || col.actualWidth}'
5339
+ // `
5340
+ // }
5341
+ headerHtml += `
5342
+ >
5343
+ <div>
5344
+ ${col.name}
5345
+ ${col.searchable === true ? this.buildSearchIcon(col, colIndex) : ''}
5346
+ </div>
5347
+ </td>`
5348
+ })
5349
+ headerHtml += `</tr>`
5350
+ })
5351
+ const dropdownEl = document.getElementById(`${this.elementId}_dropdownContainer`)
5352
+ this.options.columns[this.options.columns.length - 1].forEach((c, i) => {
5353
+ if (c.searchable && c.isExternalSearch === true) {
5354
+ const testEl = document.getElementById(`${this.elementId}_columnSearch_${c.dimId || i}`)
5355
+ if (!testEl) {
5356
+ const newE = document.createElement('div')
5357
+ newE.id = `${this.elementId}_columnSearch_${c.dimId || i}`
5358
+ newE.className = 'websy-modal-dropdown'
5359
+ dropdownEl.appendChild(newE)
5360
+ }
5361
+ }
5362
+ })
5363
+ return headerHtml
5364
+ }
5365
+ buildSearchIcon (col, index) {
5366
+ return `
5367
+ <div class="websy-table-search-icon" data-col-id="${col.dimId}" data-col-index="${index}">
5368
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 512 512"><title>ionicons-v5-f</title><path d="M221.09,64A157.09,157.09,0,1,0,378.18,221.09,157.1,157.1,0,0,0,221.09,64Z" style="fill:none;stroke:#000;stroke-miterlimit:10;stroke-width:32px"/><line x1="338.29" y1="338.29" x2="448" y2="448" style="fill:none;stroke:#000;stroke-linecap:round;stroke-miterlimit:10;stroke-width:32px"/></svg>
5369
+ </div>
5370
+ `
5371
+ }
5372
+ buildTotalHtml (useWidths = false) {
5373
+ if (!this.options.totals) {
5374
+ return ''
5375
+ }
5376
+ let totalHtml = `<tr class="websy-table-row websy-table-total-row">`
5377
+ this.options.totals.forEach((col, colIndex) => {
5378
+ totalHtml += `<td
5379
+ class='websy-table-cell'
5380
+ colspan='${col.colspan || 1}'
5381
+ rowspan='${col.rowspan || 1}'
5382
+ `
5383
+ if (useWidths === true) {
5384
+ totalHtml += `
5385
+ style='width: ${this.options.columns[this.options.columns.length - 1][colIndex].width || this.options.columns[this.options.columns.length - 1][colIndex].actualWidth}px'
5386
+ width='${col.width || col.actualWidth}'
5387
+ `
5388
+ }
5389
+ totalHtml += `
5390
+ >
5391
+ ${col.value}
5392
+ </td>`
5393
+ })
5394
+ totalHtml += `</tr>`
5395
+ return totalHtml
5396
+ }
5397
+ calculateSizes (sample = [], totalRowCount, totalColumnCount, pinnedColumns) {
5398
+ this.totalRowCount = totalRowCount // probably need some error handling here if no value is passed in
5399
+ this.totalColumnCount = totalColumnCount // probably need some error handling here if no value is passed in
5400
+ this.pinnedColumns = pinnedColumns // probably need some error handling here if no value is passed in
5401
+ let outerEl = document.getElementById(this.elementId)
5402
+ let tableEl = document.getElementById(`${this.elementId}_tableContainer`)
5403
+ let headEl = document.getElementById(`${this.elementId}_tableHeader`)
5404
+ headEl.style.width = 'auto'
5405
+ headEl.innerHTML = this.buildHeaderHtml()
5406
+ this.sizes.outer = outerEl.getBoundingClientRect()
5407
+ this.sizes.table = tableEl.getBoundingClientRect()
5408
+ this.sizes.header = headEl.getBoundingClientRect()
5409
+ let maxWidth
5410
+ if (typeof this.options.maxColWidth === 'number') {
5411
+ maxWidth = this.options.maxColWidth
5412
+ }
5413
+ else if (this.options.maxColWidth.indexOf('%') !== -1) {
5414
+ maxWidth = this.sizes.outer.width * (+(this.options.maxColWidth.replace('%', '')) / 100)
5415
+ }
5416
+ else if (this.options.maxColWidth.indexOf('px') !== -1) {
5417
+ maxWidth = +this.options.maxColWidth.replace('px', '')
5418
+ }
5419
+ let bodyEl = document.getElementById(`${this.elementId}_tableBody`)
5420
+ bodyEl.style.width = 'auto'
5421
+ bodyEl.innerHTML = this.buildBodyHtml([sample])
5422
+ let footerEl = document.getElementById(`${this.elementId}_tableFooter`)
5423
+ footerEl.innerHTML = this.buildTotalHtml()
5424
+ this.sizes.total = footerEl.getBoundingClientRect()
5425
+ const rows = Array.from(tableEl.querySelectorAll('.websy-table-row'))
5426
+ let totalWidth = 0
5427
+ this.sizes.scrollableWidth = this.sizes.outer.width
5428
+ rows.forEach((row, rowIndex) => {
5429
+ Array.from(row.children).forEach((col, colIndex) => {
5430
+ let colSize = col.getBoundingClientRect()
5431
+ this.sizes.cellHeight = colSize.height
5432
+ if (this.options.columns[this.options.columns.length - 1][colIndex]) {
5433
+ if (!this.options.columns[this.options.columns.length - 1][colIndex].actualWidth) {
5434
+ this.options.columns[this.options.columns.length - 1][colIndex].actualWidth = 0
5435
+ }
5436
+ this.options.columns[this.options.columns.length - 1][colIndex].actualWidth = Math.min(Math.max(this.options.columns[this.options.columns.length - 1][colIndex].actualWidth, colSize.width), maxWidth)
5437
+ this.options.columns[this.options.columns.length - 1][colIndex].cellHeight = colSize.height
5438
+ }
5439
+ })
5440
+ })
5441
+ this.options.columns[this.options.columns.length - 1].forEach((col, colIndex) => {
5442
+ if (colIndex < this.pinnedColumns) {
5443
+ this.sizes.scrollableWidth -= col.actualWidth
5444
+ }
5445
+ })
5446
+ this.sizes.totalWidth = this.options.columns[this.options.columns.length - 1].reduce((a, b) => a + (b.width || b.actualWidth), 0)
5447
+ const outerSize = outerEl.getBoundingClientRect()
5448
+ if (this.sizes.totalWidth < outerSize.width) {
5449
+ this.sizes.totalWidth = 0
5450
+ let equalWidth = outerSize.width / this.options.columns[this.options.columns.length - 1].length
5451
+ this.options.columns[this.options.columns.length - 1].forEach((c, i) => {
5452
+ if (!c.width) {
5453
+ if (c.actualWidth < equalWidth) {
5454
+ // adjust the width
5455
+ c.actualWidth = equalWidth
5456
+ }
5457
+ }
5458
+ this.sizes.totalWidth += c.width || c.actualWidth
5459
+ equalWidth = (outerSize.width - this.sizes.totalWidth) / (this.options.columns[this.options.columns.length - 1].length - (i + 1))
5460
+ })
5461
+ }
5462
+ // take the height of the last cell as the official height for data cells
5463
+ // this.sizes.dataCellHeight = this.options.columns[this.options.columns.length - 1].cellHeight
5464
+ headEl.innerHTML = ''
5465
+ bodyEl.innerHTML = ''
5466
+ footerEl.innerHTML = ''
5467
+ headEl.style.width = 'initial'
5468
+ bodyEl.style.width = 'initial'
5469
+ this.sizes.bodyHeight = this.sizes.table.height - (this.sizes.header.height + this.sizes.total.height)
5470
+ this.sizes.rowsToRender = Math.ceil(this.sizes.bodyHeight / this.sizes.cellHeight)
5471
+ this.sizes.rowsToRenderPrecise = this.sizes.bodyHeight / this.sizes.cellHeight
5472
+ this.startRow = 0
5473
+ this.endRow = this.sizes.rowsToRender
5474
+ this.startCol = 0
5475
+ this.endCol = this.options.columns[this.options.columns.length - 1].length
5476
+ if (this.sizes.rowsToRender < this.totalRowCount) {
5477
+ this.vScrollRequired = true
5478
+ }
5479
+ if (this.sizes.totalWidth > this.sizes.outer.width) {
5480
+ this.hScrollRequired = true
5481
+ }
5482
+ this.options.allColumns = this.options.columns.map(c => c)
5483
+ console.log('sizes', this.sizes)
5484
+ return this.sizes
5485
+ }
5486
+ createSample (data) {
5487
+ let output = []
5488
+ this.options.columns[this.options.columns.length - 1].forEach((col, colIndex) => {
5489
+ if (col.maxLength) {
5490
+ output.push({value: new Array(col.maxLength).fill('W').join('')})
5491
+ }
5492
+ else if (data) {
5493
+ let longest = ''
5494
+ for (let i = 0; i < Math.min(data.length, 1000); i++) {
5495
+ if (longest.length < data[i][colIndex].value.length) {
5496
+ longest = data[i][colIndex].value
5497
+ }
5498
+ }
5499
+ output.push({value: longest})
5500
+ }
5501
+ else {
5502
+ output.push({value: ''})
5503
+ }
5504
+ })
5505
+ return output
5506
+ }
5507
+ handleClick (event) {
5508
+ if (event.target.classList.contains('websy-table-search-icon')) {
5509
+ console.log('clicked on search icon')
5510
+ const colIndex = +event.target.getAttribute('data-col-index')
5511
+ if (this.options.columns[this.options.columns.length - 1][colIndex].onSearch) {
5512
+ this.options.columns[this.options.columns.length - 1][colIndex].onSearch(event, this.options.columns[this.options.columns.length - 1][colIndex])
5513
+ }
5514
+ }
5515
+ }
5516
+ handleMouseDown (event) {
5517
+ if (event.target.classList.contains('websy-scroll-handle-y')) {
5518
+ // set up the scroll start values
5519
+ this.scrollDragging = true
5520
+ this.scrollDirection = 'y'
5521
+ const scrollHandleEl = document.getElementById(`${this.elementId}_vScrollHandle`)
5522
+ this.handleYStart = scrollHandleEl.offsetTop
5523
+ this.mouseYStart = event.pageY
5524
+ console.log('mouse down', this.handleYStart, this.mouseYStart)
5525
+ console.log(scrollHandleEl.offsetTop)
5526
+ }
5527
+ else if (event.target.classList.contains('websy-scroll-handle-x')) {
5528
+ this.scrollDragging = true
5529
+ this.scrollDirection = 'x'
5530
+ const scrollHandleEl = document.getElementById(`${this.elementId}_hScrollHandle`)
5531
+ this.handleXStart = scrollHandleEl.offsetLeft
5532
+ this.mouseXStart = event.pageX
5533
+ }
5534
+ }
5535
+ handleMouseMove (event) {
5536
+ // event.preventDefault()
5537
+ if (this.scrollDragging === true) {
5538
+ if (this.scrollDirection === 'y') {
5539
+ const diff = event.pageY - this.mouseYStart
5540
+ this.scrollY(diff)
5541
+ }
5542
+ else if (this.scrollDirection === 'x') {
5543
+ const diff = event.pageX - this.mouseXStart
5544
+ this.scrollX(diff)
5545
+ }
5546
+ }
5547
+ }
5548
+ handleMouseUp (event) {
5549
+ this.scrollDragging = false
5550
+ this.cellDragging = false
5551
+ this.handleYStart = null
5552
+ this.mouseYStart = null
5553
+ this.handleXStart = null
5554
+ this.mouseXStart = null
5555
+ }
5556
+ handleScrollWheel (event) {
5557
+ event.preventDefault()
5558
+ console.log('scrollwheel', event)
5559
+ if (Math.abs(event.deltaX) > Math.abs(event.deltaY)) {
5560
+ this.scrollX(Math.max(-5, Math.min(5, event.deltaX)))
5561
+ }
5562
+ else {
5563
+ this.scrollY(Math.max(-5, Math.min(5, event.deltaY)))
5564
+ }
5565
+ }
5566
+ hideError () {
5567
+ const el = document.getElementById(`${this.elementId}_tableContainer`)
5568
+ if (el) {
5569
+ el.classList.remove('has-error')
5570
+ }
5571
+ const tableEl = document.getElementById(`${this.elementId}_tableInner`)
5572
+ tableEl.classList.remove('hidden')
5573
+ const containerEl = document.getElementById(`${this.elementId}_errorContainer`)
5574
+ if (containerEl) {
5575
+ containerEl.classList.remove('active')
5576
+ }
5577
+ }
5578
+ hideLoading () {
5579
+ this.loadingDialog.hide()
5580
+ }
5581
+ render (data, calcSizes = true) {
5582
+ if (!this.options.columns) {
5583
+ console.log(`No columns provided for table with ID ${this.elementId}`)
5584
+ return
5585
+ }
5586
+ if (this.options.columns.length === 0) {
5587
+ console.log(`No columns provided for table with ID ${this.elementId}`)
5588
+ return
5589
+ }
5590
+ // this.data = []
5591
+ // Adjust the sizing of the header/body/footer
5592
+ if (calcSizes === true) {
5593
+ const sample = this.createSample(data)
5594
+ this.calculateSizes(sample, data.length, (data[0] || []).length, 0)
5595
+ }
5596
+ console.log(this.options.columns)
5597
+ const tableInnerEl = document.getElementById(`${this.elementId}_tableInner`)
5598
+ if (tableInnerEl) {
5599
+ tableInnerEl.style.width = `${this.sizes.totalWidth}px`
5600
+ }
5601
+ this.renderColumnHeaders()
5602
+ this.renderTotals()
5603
+ if (data) {
5604
+ this.appendRows(data)
5605
+ }
5606
+ let bodyEl = document.getElementById(`${this.elementId}_tableBody`)
5607
+ // bodyEl.innerHTML = this.buildBodyHtml(data, true)
5608
+ bodyEl.style.height = `calc(100% - ${this.sizes.header.height}px - ${this.sizes.total.height}px)`
5609
+ if (this.options.virtualScroll === true) {
5610
+ // set the scroll element positions
5611
+ let vScrollEl = document.getElementById(`${this.elementId}_vScrollContainer`)
5612
+ let vHandleEl = document.getElementById(`${this.elementId}_vScrollHandle`)
5613
+ if (this.vScrollRequired === true) {
5614
+ vScrollEl.style.top = `${this.sizes.header.height + this.sizes.total.height}px`
5615
+ vScrollEl.style.height = `${this.sizes.bodyHeight}px`
5616
+ vHandleEl.style.height = Math.max(this.options.minHandleSize, this.sizes.bodyHeight * (this.sizes.rowsToRenderPrecise / this.totalRowCount)) + 'px'
5617
+ }
5618
+ else {
5619
+ vHandleEl.style.height = '0px'
5620
+ }
5621
+ let hScrollEl = document.getElementById(`${this.elementId}_hScrollContainer`)
5622
+ let hHandleEl = document.getElementById(`${this.elementId}_hScrollHandle`)
5623
+ if (this.hScrollRequired === true) {
5624
+ hScrollEl.style.left = `${this.sizes.table.width - this.sizes.scrollableWidth}px`
5625
+ hScrollEl.style.width = `${this.sizes.scrollableWidth - 20}px`
5626
+ hHandleEl.style.width = Math.max(this.options.minHandleSize, this.sizes.scrollableWidth * (this.sizes.scrollableWidth / this.sizes.totalWidth)) + 'px'
5627
+ }
5628
+ else {
5629
+ hHandleEl.style.height = '0px'
5630
+ }
5631
+ }
5632
+ }
5633
+ renderColumnHeaders () {
5634
+ let headEl = document.getElementById(`${this.elementId}_tableHeader`)
5635
+ if (headEl) {
5636
+ headEl.innerHTML = this.buildHeaderHtml(true)
5637
+ }
5638
+ }
5639
+ renderTotals () {
5640
+ let headEl = document.getElementById(`${this.elementId}_tableHeader`)
5641
+ let totalHtml = this.buildTotalHtml(true)
5642
+ if (this.options.showTotalsAbove === true) {
5643
+ headEl.innerHTML += totalHtml
5644
+ }
5645
+ else {
5646
+ const footerEl = document.getElementById(`${this.elementId}_tableFooter`)
5647
+ if (footerEl) {
5648
+ footerEl.innerHTML = totalHtml
5649
+ }
5650
+ }
5651
+ }
5652
+ resize () {
5653
+
5654
+ }
5655
+ showError (options) {
5656
+ const el = document.getElementById(`${this.elementId}_tableContainer`)
5657
+ if (el) {
5658
+ el.classList.add('has-error')
5659
+ }
5660
+ const tableEl = document.getElementById(`${this.elementId}_tableInner`)
5661
+ tableEl.classList.add('hidden')
5662
+ const containerEl = document.getElementById(`${this.elementId}_errorContainer`)
5663
+ if (containerEl) {
5664
+ containerEl.classList.add('active')
5665
+ }
5666
+ if (options.title) {
5667
+ const titleEl = document.getElementById(`${this.elementId}_errorTitle`)
5668
+ if (titleEl) {
5669
+ titleEl.innerHTML = options.title
5670
+ }
5671
+ }
5672
+ if (options.message) {
5673
+ const messageEl = document.getElementById(`${this.elementId}_errorMessage`)
5674
+ if (messageEl) {
5675
+ messageEl.innerHTML = options.message
5676
+ }
5677
+ }
5678
+ }
5679
+ scrollX (diff) {
5680
+ const scrollContainerEl = document.getElementById(`${this.elementId}_hScrollContainer`)
5681
+ const scrollHandleEl = document.getElementById(`${this.elementId}_hScrollHandle`)
5682
+ let handlePos
5683
+ if (typeof this.handleXStart !== 'undefined' && this.handleXStart !== null) {
5684
+ handlePos = this.handleXStart + diff
5685
+ }
5686
+ else {
5687
+ handlePos = scrollHandleEl.offsetLeft + diff
5688
+ }
5689
+ const scrollableSpace = scrollContainerEl.getBoundingClientRect().width - scrollHandleEl.getBoundingClientRect().width
5690
+ console.log('dragging x', diff, scrollContainerEl.getBoundingClientRect().width - scrollHandleEl.getBoundingClientRect().width)
5691
+ scrollHandleEl.style.left = Math.min(scrollableSpace, Math.max(0, handlePos)) + 'px'
5692
+ if (this.options.onScroll) {
5693
+ let actualLeft = (this.sizes.totalWidth - this.sizes.scrollableWidth) * (Math.min(scrollableSpace, Math.max(0, handlePos)) / scrollableSpace)
5694
+ let cumulativeWidth = 0
5695
+ this.startCol = 0
5696
+ this.endCol = 0
5697
+ for (let i = 0; i < this.options.allColumns[this.options.allColumns.length - 1].length; i++) {
5698
+ cumulativeWidth += this.options.allColumns[this.options.allColumns.length - 1][i].actualWidth
5699
+ console.log('actualLeft', actualLeft, this.sizes.totalWidth, cumulativeWidth, cumulativeWidth + this.options.allColumns[this.options.allColumns.length - 1][i].actualWidth)
5700
+ if (actualLeft < cumulativeWidth) {
5701
+ this.startCol = i
5702
+ break
5703
+ }
5704
+ }
5705
+ cumulativeWidth = 0
5706
+ for (let i = this.startCol; i < this.options.allColumns[this.options.allColumns.length - 1].length; i++) {
5707
+ cumulativeWidth += this.options.allColumns[this.options.allColumns.length - 1][i].actualWidth
5708
+ if (cumulativeWidth < this.sizes.scrollableWidth) {
5709
+ this.endCol = i
5710
+ }
5711
+ }
5712
+ if (this.endCol < this.options.allColumns[this.options.allColumns.length - 1].length - 1) {
5713
+ this.endCol += 1
5714
+ }
5715
+ if (this.endCol === this.options.allColumns[this.options.allColumns.length - 1].length - 1 && cumulativeWidth > this.sizes.totalWidth) {
5716
+ this.startCol += 1
5717
+ }
5718
+ this.endCol = Math.max(this.startCol, this.endCol)
5719
+ this.options.onScroll('y', this.startRow, this.endRow, this.startCol, this.endCol)
5720
+ }
5721
+ }
5722
+ scrollY (diff) {
5723
+ const scrollContainerEl = document.getElementById(`${this.elementId}_vScrollContainer`)
5724
+ const scrollHandleEl = document.getElementById(`${this.elementId}_vScrollHandle`)
5725
+ let handlePos
5726
+ if (typeof this.handleYStart !== 'undefined' && this.handleYStart !== null) {
5727
+ handlePos = this.handleYStart + diff
5728
+ }
5729
+ else {
5730
+ console.log('appending not resetting')
5731
+ handlePos = scrollHandleEl.offsetTop + diff
5732
+ }
5733
+ const scrollableSpace = scrollContainerEl.getBoundingClientRect().height - scrollHandleEl.getBoundingClientRect().height
5734
+ console.log('dragging y', (diff), scrollContainerEl.getBoundingClientRect().height - scrollHandleEl.getBoundingClientRect().height)
5735
+ scrollHandleEl.style.top = Math.min(scrollableSpace, Math.max(0, handlePos)) + 'px'
5736
+ if (this.options.onScroll) {
5737
+ this.startRow = Math.min(this.totalRowCount - this.sizes.rowsToRender, Math.max(0, Math.round((this.totalRowCount - this.sizes.rowsToRender) * (handlePos / scrollableSpace))))
5738
+ this.endRow = this.startRow + this.sizes.rowsToRender
5739
+ if (this.endRow === this.totalRowCount) {
5740
+ this.startRow += 1
5741
+ }
5742
+ this.options.onScroll('y', this.startRow, this.endRow, this.startCol, this.endCol)
5743
+ }
5744
+ }
5745
+ showLoading (options) {
5746
+ this.loadingDialog.show(options)
5747
+ }
5748
+ }
5749
+
4827
5750
  /* global d3 include WebsyDesigns */
4828
5751
  class WebsyChart {
4829
5752
  constructor (elementId, options) {
@@ -5748,7 +6671,7 @@ bars
5748
6671
  .attr('x', getBarX.bind(this))
5749
6672
  .attr('y', getBarY.bind(this))
5750
6673
  .transition(this.transition)
5751
- .attr('fill', series.color)
6674
+ .attr('fill', d => d.color || series.color)
5752
6675
 
5753
6676
  bars
5754
6677
  .enter()
@@ -5758,7 +6681,7 @@ bars
5758
6681
  .attr('x', getBarX.bind(this))
5759
6682
  .attr('y', getBarY.bind(this))
5760
6683
  // .transition(this.transition)
5761
- .attr('fill', series.color)
6684
+ .attr('fill', d => d.color || series.color)
5762
6685
  .attr('class', d => {
5763
6686
  return `bar bar_${series.key}`
5764
6687
  })
@@ -5788,7 +6711,7 @@ if (this.options.showLabels) {
5788
6711
  .attr('y', getLabelY.bind(this))
5789
6712
  .attr('class', `label_${series.key}`)
5790
6713
  .style('font-size', `${this.options.labelSize || this.options.fontSize}px`)
5791
- .style('fill', this.options.labelColor || WebsyDesigns.WebsyUtils.getLightDark(series.color))
6714
+ .style('fill', d => this.options.labelColor || WebsyDesigns.WebsyUtils.getLightDark(d.color || series.color))
5792
6715
  .transition(this.transition)
5793
6716
  .text(d => d.y.label || d.y.value)
5794
6717
 
@@ -5801,7 +6724,7 @@ if (this.options.showLabels) {
5801
6724
  .attr('alignment-baseline', 'central')
5802
6725
  .attr('text-anchor', this.options.orientation === 'horizontal' ? 'left' : 'middle')
5803
6726
  .style('font-size', `${this.options.labelSize || this.options.fontSize}px`)
5804
- .style('fill', this.options.labelColor || WebsyDesigns.WebsyUtils.getLightDark(series.color))
6727
+ .style('fill', d => this.options.labelColor || WebsyDesigns.WebsyUtils.getLightDark(d.color || series.color))
5805
6728
  .text(d => d.y.label || d.y.value)
5806
6729
  .each(function (d, i) {
5807
6730
  if (that.options.orientation === 'horizontal') {
@@ -6495,6 +7418,8 @@ const WebsyDesigns = {
6495
7418
  Form: WebsyForm,
6496
7419
  WebsyDatePicker,
6497
7420
  DatePicker: WebsyDatePicker,
7421
+ WebsyDragDrop,
7422
+ DragDrop: WebsyDragDrop,
6498
7423
  WebsyDropdown,
6499
7424
  Dropdown: WebsyDropdown,
6500
7425
  WebsyResultList,
@@ -6507,8 +7432,10 @@ const WebsyDesigns = {
6507
7432
  Router: WebsyRouter,
6508
7433
  WebsyTable,
6509
7434
  WebsyTable2,
7435
+ WebsyTable3,
6510
7436
  Table: WebsyTable,
6511
7437
  Table2: WebsyTable2,
7438
+ Table3: WebsyTable3,
6512
7439
  WebsyChart,
6513
7440
  Chart: WebsyChart,
6514
7441
  WebsyChartTooltip,
@@ -6535,5 +7462,6 @@ const WebsyDesigns = {
6535
7462
  }
6536
7463
 
6537
7464
  WebsyDesigns.service = new WebsyDesigns.APIService('')
7465
+ window.GlobalPubSub = new WebsyPubSub('empty', {})
6538
7466
 
6539
7467
  export default WebsyDesigns