@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.
@@ -11,6 +11,7 @@
11
11
  WebsyResultList
12
12
  WebsyTable
13
13
  WebsyTable2
14
+ WebsyTable3
14
15
  WebsyIcons
15
16
  WebsyChart
16
17
  WebsyChartTooltip
@@ -27,6 +28,8 @@
27
28
  WebsyLogin
28
29
  WebsySignup
29
30
  ResponsiveText
31
+ WebsyDragDrop
32
+ WebsySearch
30
33
  Pager
31
34
  */
32
35
 
@@ -609,6 +612,7 @@ class WebsyDatePicker {
609
612
  if (typeof d === 'number') {
610
613
  d = new Date(d)
611
614
  }
615
+ // d.setTime(d.getTime() + d.getTimezoneOffset() * 60000)
612
616
  return new Date(d.setHours(0, 0, 0, 0))
613
617
  }
614
618
  handleClick (event) {
@@ -627,11 +631,7 @@ class WebsyDatePicker {
627
631
  this.updateRange(index)
628
632
  }
629
633
  else if (event.target.classList.contains('websy-dp-date')) {
630
- // if (event.target.classList.contains('websy-disabled-date')) {
631
- // return
632
- // }
633
- // const timestamp = event.target.id.split('_')[0]
634
- // this.selectDate(+timestamp)
634
+ //
635
635
  }
636
636
  else if (event.target.classList.contains('websy-dp-confirm')) {
637
637
  this.close(true)
@@ -660,7 +660,8 @@ class WebsyDatePicker {
660
660
  handleMouseDown (event) {
661
661
  if (this.shiftPressed === true && this.currentselection.length > 0) {
662
662
  this.mouseDownId = this.currentselection[this.currentselection.length - 1]
663
- this.selectDate(+event.target.id.split('_')[1])
663
+ let dateId = event.target.getAttribute('data-id')
664
+ this.selectDate(+dateId)
664
665
  }
665
666
  else {
666
667
  this.mouseDown = true
@@ -673,7 +674,7 @@ class WebsyDatePicker {
673
674
  this.currentselection = []
674
675
  this.customRangeSelected = false
675
676
  }
676
- this.mouseDownId = +event.target.id.split('_')[1]
677
+ this.mouseDownId = +event.target.getAttribute('data-id')
677
678
  this.selectDate(this.mouseDownId)
678
679
  }
679
680
  }
@@ -684,9 +685,10 @@ class WebsyDatePicker {
684
685
  if (event.target.classList.contains('websy-disabled-date')) {
685
686
  return
686
687
  }
687
- if (event.target.id.split('_')[1] !== this.mouseDownId) {
688
+ let dateId = +event.target.getAttribute('data-id')
689
+ if (dateId !== this.mouseDownId) {
688
690
  this.dragging = true
689
- this.selectDate(+event.target.id.split('_')[1])
691
+ this.selectDate(dateId)
690
692
  }
691
693
  }
692
694
  }
@@ -734,6 +736,7 @@ class WebsyDatePicker {
734
736
  let rangeEnd
735
737
  if (this.options.mode === 'date') {
736
738
  d = this.floorDate(new Date(this.selectedRangeDates[0].getTime() + (i * this.oneDay)))
739
+ d.setHours(0, 0, 0, 0)
737
740
  d = d.getTime()
738
741
  rangeStart = this.selectedRangeDates[0].getTime()
739
742
  rangeEnd = this.selectedRangeDates[this.selectedRangeDates.length - 1].getTime()
@@ -1003,7 +1006,7 @@ class WebsyDatePicker {
1003
1006
  }
1004
1007
  html += paddedDays.join('')
1005
1008
  }
1006
- 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('')
1009
+ 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('')
1007
1010
  html += `
1008
1011
  </ul>
1009
1012
  </div>
@@ -1124,7 +1127,7 @@ class WebsyDatePicker {
1124
1127
  selectRange (index, confirm = true) {
1125
1128
  if (this.options.ranges[this.options.mode][index]) {
1126
1129
  this.selectedRangeDates = [...this.options.ranges[this.options.mode][index].range]
1127
- this.currentselection = [...this.options.ranges[this.options.mode][index].range]
1130
+ this.currentselection = this.options.ranges[this.options.mode][index].range.map(d => d.getTime())
1128
1131
  this.selectedRange = +index
1129
1132
  const el = document.getElementById(`${this.elementId}_header`)
1130
1133
  if (el) {
@@ -1409,18 +1412,25 @@ class WebsyDropdown {
1409
1412
  if (typeof d.index === 'undefined') {
1410
1413
  d.index = i
1411
1414
  }
1415
+ d.currentIndex = i
1412
1416
  return d
1413
- })
1414
- const el = document.getElementById(`${this.elementId}_items`)
1415
- if (el.childElementCount === 0) {
1416
- this.render()
1417
+ })
1418
+ const headerEl = document.getElementById(`${this.elementId}_header`)
1419
+ if (headerEl) {
1420
+ headerEl.classList[`${this.options.allowClear === true ? 'add' : 'remove'}`]('allow-clear')
1417
1421
  }
1418
- else {
1419
- if (this.options.items.length === 0) {
1420
- this.options.items = [{label: this.options.noItemsText || 'No Items'}]
1422
+ const el = document.getElementById(`${this.elementId}_items`)
1423
+ if (el) {
1424
+ if (el.childElementCount === 0) {
1425
+ this.render()
1421
1426
  }
1422
- this.renderItems()
1423
- }
1427
+ else {
1428
+ if (this.options.items.length === 0) {
1429
+ this.options.items = [{label: this.options.noItemsText || 'No Items'}]
1430
+ }
1431
+ this.renderItems()
1432
+ }
1433
+ }
1424
1434
  }
1425
1435
  get data () {
1426
1436
  return this.options.items
@@ -1661,6 +1671,10 @@ class WebsyDropdown {
1661
1671
  const labelEl = document.getElementById(`${this.elementId}_selectedItems`)
1662
1672
  const inputEl = document.getElementById(`${this.elementId}_input`)
1663
1673
  const itemEls = el.querySelectorAll(`.websy-dropdown-item`)
1674
+ let dataToUse = this._originalData
1675
+ if (this.options.onSearch) {
1676
+ dataToUse = this.options.items
1677
+ }
1664
1678
  for (let i = 0; i < itemEls.length; i++) {
1665
1679
  itemEls[i].classList.remove('active')
1666
1680
  let index = itemEls[i].getAttribute('data-index')
@@ -1696,14 +1710,14 @@ class WebsyDropdown {
1696
1710
  }
1697
1711
  else if (this.selectedItems.length > 1) {
1698
1712
  if (this.options.showCompleteSelectedList === true) {
1699
- let selectedLabels = this.selectedItems.map(s => this.options.items[s].label || this.options.items[s].value).join(this.options.multiValueDelimiter)
1700
- let selectedValues = this.selectedItems.map(s => this.options.items[s].value || this.options.items[s].label).join(this.options.multiValueDelimiter)
1713
+ let selectedLabels = this.selectedItems.map(s => dataToUse[s].label || dataToUse[s].value).join(this.options.multiValueDelimiter)
1714
+ let selectedValues = this.selectedItems.map(s => dataToUse[s].value || dataToUse[s].label).join(this.options.multiValueDelimiter)
1701
1715
  labelEl.innerHTML = selectedLabels
1702
1716
  labelEl.setAttribute('data-info', selectedLabels)
1703
1717
  inputEl.value = selectedValues
1704
1718
  }
1705
1719
  else {
1706
- let selectedValues = this.selectedItems.map(s => this.options.items[s].value || this.options.items[s].label).join(this.options.multiValueDelimiter)
1720
+ let selectedValues = this.selectedItems.map(s => dataToUse[s].value || dataToUse[s].label).join(this.options.multiValueDelimiter)
1707
1721
  labelEl.innerHTML = `${this.selectedItems.length} selected`
1708
1722
  labelEl.setAttribute('data-info', '')
1709
1723
  inputEl.value = selectedValues
@@ -1717,6 +1731,10 @@ class WebsyDropdown {
1717
1731
  }
1718
1732
  }
1719
1733
  updateSelected (index) {
1734
+ let dataToUse = this._originalData && this._originalData.length > 0 ? this._originalData : this.options.items
1735
+ if (this.options.onSearch) {
1736
+ dataToUse = this.options.items
1737
+ }
1720
1738
  if (typeof index !== 'undefined' && index !== null) {
1721
1739
  let pos = this.selectedItems.indexOf(index)
1722
1740
  if (this.options.multiSelect === false) {
@@ -1731,10 +1749,11 @@ class WebsyDropdown {
1731
1749
  }
1732
1750
  }
1733
1751
  }
1734
- const item = this.options.items[index]
1752
+ // const item = this.options.items[index]
1753
+ const item = dataToUse[index]
1735
1754
  this.updateHeader(item)
1736
1755
  if (item && this.options.onItemSelected) {
1737
- this.options.onItemSelected(item, this.selectedItems, this.options.items, this.options)
1756
+ this.options.onItemSelected(item, this.selectedItems, dataToUse, this.options)
1738
1757
  }
1739
1758
  if (this.options.closeAfterSelection === true) {
1740
1759
  this.close()
@@ -1742,6 +1761,276 @@ class WebsyDropdown {
1742
1761
  }
1743
1762
  }
1744
1763
 
1764
+ /* global WebsyDesigns GlobalPubSub */
1765
+ class WebsyDragDrop {
1766
+ constructor (elementId, options) {
1767
+ const DEFAULTS = {
1768
+ items: [],
1769
+ orientation: 'horizontal',
1770
+ dropPlaceholder: 'Drop item here'
1771
+ }
1772
+ this.busy = false
1773
+ this.options = Object.assign({}, DEFAULTS, options)
1774
+ this.elementId = elementId
1775
+ if (!elementId) {
1776
+ console.log('No element Id provided for Websy DragDrop')
1777
+ return
1778
+ }
1779
+ const el = document.getElementById(elementId)
1780
+ if (el) {
1781
+ el.innerHTML = `
1782
+ <div id='${this.elementId}_container' class='websy-drag-drop-container ${this.options.orientation}'>
1783
+ <div>
1784
+ </div>
1785
+ `
1786
+ el.addEventListener('click', this.handleClick.bind(this))
1787
+ el.addEventListener('dragstart', this.handleDragStart.bind(this))
1788
+ el.addEventListener('dragover', this.handleDragOver.bind(this))
1789
+ el.addEventListener('dragleave', this.handleDragLeave.bind(this))
1790
+ el.addEventListener('drop', this.handleDrop.bind(this))
1791
+ window.addEventListener('dragend', this.handleDragEnd.bind(this))
1792
+ }
1793
+ else {
1794
+ console.error(`No element found with ID ${this.elementId}`)
1795
+ }
1796
+ GlobalPubSub.subscribe(this.elementId, 'requestForDDItem', this.handleRequestForItem.bind(this))
1797
+ GlobalPubSub.subscribe(this.elementId, 'add', this.addItem.bind(this))
1798
+ this.render()
1799
+ }
1800
+ addItem (data) {
1801
+ if (data.target === this.elementId && this.busy === false) {
1802
+ this.busy = true
1803
+ console.log('adding item to dd')
1804
+ // check that an item with the same id doesn't already exist
1805
+ let index = this.getItemIndex(data.item.id)
1806
+ if (index === -1) {
1807
+ this.options.items.splice(data.index, 0, data.item)
1808
+ const startEl = document.getElementById(`${this.elementId}start_item`)
1809
+ if (startEl) {
1810
+ if (this.options.items.length === 0) {
1811
+ startEl.classList.add('empty')
1812
+ }
1813
+ else {
1814
+ startEl.classList.remove('empty')
1815
+ }
1816
+ }
1817
+ if (this.options.onItemAdded) {
1818
+ this.options.onItemAdded()
1819
+ }
1820
+ }
1821
+ this.busy = false
1822
+ }
1823
+ }
1824
+ createItemHtml (elementId, index, item) {
1825
+ if (!item.id) {
1826
+ item.id = WebsyDesigns.Utils.createIdentity()
1827
+ }
1828
+ let html = `
1829
+ <div id='${item.id}_item' class='websy-dragdrop-item' draggable='true' data-id='${item.id}'>
1830
+ <div id='${item.id}_itemInner' class='websy-dragdrop-item-inner' data-id='${item.id}'>
1831
+ `
1832
+ if (item.component) {
1833
+ html += `<div id='${item.id}_component'></div>`
1834
+ }
1835
+ else {
1836
+ html += `${item.html || item.label || ''}`
1837
+ }
1838
+ html += `
1839
+ </div>
1840
+ <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>
1841
+ </div>
1842
+ `
1843
+ return html
1844
+ }
1845
+ getItemIndex (id) {
1846
+ for (let i = 0; i < this.options.items.length; i++) {
1847
+ if (this.options.items[i].id === id) {
1848
+ return i
1849
+ }
1850
+ }
1851
+ return -1
1852
+ }
1853
+ handleClick (event) {
1854
+
1855
+ }
1856
+ handleDragStart (event) {
1857
+ this.draggedId = event.target.getAttribute('data-id')
1858
+ event.dataTransfer.effectAllowed = 'move'
1859
+ event.dataTransfer.setData('application/wd-item', JSON.stringify({el: event.target.id, id: this.elementId, itemId: this.draggedId}))
1860
+ // console.log('drag start', event)
1861
+ event.target.style.opacity = 0.5
1862
+ this.dragging = true
1863
+ }
1864
+ handleDragOver (event) {
1865
+ // console.log('drag over', event.target.classList)
1866
+ if (event.preventDefault) {
1867
+ event.preventDefault()
1868
+ }
1869
+ if (!event.target.classList.contains('droppable')) {
1870
+ return
1871
+ }
1872
+ event.target.classList.add('drag-over')
1873
+ }
1874
+ handleDragLeave (event) {
1875
+ // console.log('drag leave', event.target.classList)
1876
+ if (!event.target.classList.contains('droppable')) {
1877
+ return
1878
+ }
1879
+ event.target.classList.remove('drag-over')
1880
+ // let side = event.target.getAttribute('data-side')
1881
+ // let id = event.target.getAttribute('data-id')
1882
+ // let droppedItem = this.options.items[id]
1883
+ // this.removeExpandedDrop(side, id, droppedItem)
1884
+ }
1885
+ handleDrop (event) {
1886
+ // console.log('drag drop')
1887
+ // console.log(event.dataTransfer.getData('application/wd-item'))
1888
+ const data = JSON.parse(event.dataTransfer.getData('application/wd-item'))
1889
+ if (event.preventDefault) {
1890
+ event.preventDefault()
1891
+ }
1892
+ if (!event.target.classList.contains('droppable')) {
1893
+ return
1894
+ }
1895
+ let side = event.target.getAttribute('data-side')
1896
+ let id = event.target.getAttribute('data-id')
1897
+ let index = this.getItemIndex(id)
1898
+ let draggedIndex = this.getItemIndex(data.id)
1899
+ let droppedItem = this.options.items[index]
1900
+ if (side === 'right') {
1901
+ index += 1
1902
+ }
1903
+ if (draggedIndex === -1) {
1904
+ // console.log('requestForDDItem')
1905
+ GlobalPubSub.publish(data.id, 'requestForDDItem', {
1906
+ group: this.options.group,
1907
+ source: data.id,
1908
+ target: this.elementId,
1909
+ index,
1910
+ id: data.itemId
1911
+ })
1912
+ }
1913
+ else if (index > draggedIndex) {
1914
+ // insert and then remove
1915
+ this.options.items.splice(index, 0, droppedItem)
1916
+ this.options.items.splice(draggedIndex, 1)
1917
+ if (this.options.onOrderUpdated) {
1918
+ this.options.onOrderUpdated()
1919
+ }
1920
+ }
1921
+ else {
1922
+ // remove and then insert
1923
+ this.options.items.splice(draggedIndex, 1)
1924
+ this.options.items.splice(index, 0, droppedItem)
1925
+ if (this.options.onOrderUpdated) {
1926
+ this.options.onOrderUpdated()
1927
+ }
1928
+ }
1929
+ // this.removeExpandedDrop(side, id, droppedItem)
1930
+ // const draggedEl = document.getElementById(`${this.elementId}_${this.draggedId}_item`)
1931
+ const draggedEl = document.getElementById(data.el)
1932
+ const droppedEl = document.getElementById(`${id}_item`)
1933
+ if (draggedEl) {
1934
+ droppedEl.insertAdjacentElement('afterend', draggedEl)
1935
+ }
1936
+ let dragOverEl = droppedEl.querySelector('.drag-over')
1937
+ if (dragOverEl) {
1938
+ dragOverEl.classList.remove('drag-over')
1939
+ }
1940
+ }
1941
+ handleDragEnd (event) {
1942
+ // console.log('drag end')
1943
+ event.target.style.opacity = 1
1944
+ this.draggedId = null
1945
+ this.dragging = false
1946
+ const startEl = document.getElementById(`${this.elementId}start_item`)
1947
+ if (startEl) {
1948
+ if (this.options.items.length === 0) {
1949
+ startEl.classList.add('empty')
1950
+ }
1951
+ else {
1952
+ startEl.classList.remove('empty')
1953
+ }
1954
+ }
1955
+ }
1956
+ handleRequestForItem (data) {
1957
+ if (data.group === this.options.group) {
1958
+ let index = this.getItemIndex(data.id)
1959
+ if (index !== -1) {
1960
+ let itemToAdd = this.options.items.splice(index, 1)
1961
+ GlobalPubSub.publish(data.target, 'add', {
1962
+ target: data.target,
1963
+ index: data.index,
1964
+ item: itemToAdd[0]
1965
+ })
1966
+ }
1967
+ }
1968
+ }
1969
+ measureItems () {
1970
+ const el = document.getElementById(`${this.elementId}_container`)
1971
+ this.options.items.forEach(d => {
1972
+
1973
+ })
1974
+ }
1975
+ // removeExpandedDrop (side, id, droppedItem) {
1976
+ // let dropEl
1977
+ // const dropImageEl = document.getElementById(`${id}_itemInner`)
1978
+ // // const placeholderEl = document.getElementById(`${this.elementId}_${id}_dropZonePlaceholder`)
1979
+ // if (side === 'left') {
1980
+ // dropEl = document.getElementById(`${this.elementId}_${id}_dropZoneLeft`)
1981
+ // dropImageEl.style.left = `0px`
1982
+ // }
1983
+ // else if (side === 'right') {
1984
+ // dropEl = document.getElementById(`${this.elementId}_${id}_dropZoneRight`)
1985
+ // }
1986
+ // else {
1987
+ // dropEl = document.getElementById(`${this.elementId}_${id}_dropZoneEnd`)
1988
+ // }
1989
+ // if (dropEl) {
1990
+ // const dropElSize = dropEl.getBoundingClientRect()
1991
+ // dropEl.style.width = `${(dropElSize.width / 2)}px`
1992
+ // dropEl.style.marginLeft = null
1993
+ // dropEl.style.border = null
1994
+ // }
1995
+ // if (placeholderEl) {
1996
+ // placeholderEl.classList.remove('active')
1997
+ // placeholderEl.style.left = null
1998
+ // placeholderEl.style.right = null
1999
+ // placeholderEl.style.width = null
2000
+ // placeholderEl.style.height = null
2001
+ // }
2002
+ // }
2003
+ removeItem (id) {
2004
+
2005
+ }
2006
+ render () {
2007
+ const el = document.getElementById(`${this.elementId}_container`)
2008
+ if (el) {
2009
+ this.measureItems()
2010
+ let html = `
2011
+ <div id='${this.elementId}start_item' class='websy-dragdrop-item ${this.options.items.length === 0 ? 'empty' : ''}' data-id='${this.elementId}start'>
2012
+ <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>
2013
+ </div>
2014
+ `
2015
+ html += this.options.items.map((d, i) => this.createItemHtml(this.elementId, i, d)).join('')
2016
+ el.innerHTML = html
2017
+ this.options.items.forEach((item, i) => {
2018
+ if (item.component) {
2019
+ if (item.isQlikPlugin && WebsyDesigns.QlikPlugin[item.component]) {
2020
+ item.instance = new WebsyDesigns.QlikPlugin[item.component](`${item.id}_component`, item.options)
2021
+ }
2022
+ else if (WebsyDesigns[item.component]) {
2023
+ item.instance = new WebsyDesigns[item.component](`${item.id}_component`, item.options)
2024
+ }
2025
+ else {
2026
+ console.error(`Component ${item.component} not found.`)
2027
+ }
2028
+ }
2029
+ })
2030
+ }
2031
+ }
2032
+ }
2033
+
1745
2034
  /* global WebsyDesigns FormData grecaptcha ENVIRONMENT GlobalPubSub */
1746
2035
  class WebsyForm {
1747
2036
  constructor (elementId, options) {
@@ -2716,18 +3005,35 @@ class WebsyPubSub {
2716
3005
  this.elementId = elementId
2717
3006
  this.subscriptions = {}
2718
3007
  }
2719
- publish (method, data) {
2720
- if (this.subscriptions[method]) {
2721
- this.subscriptions[method].forEach(fn => {
2722
- fn(data)
2723
- })
3008
+ publish (id, method, data) {
3009
+ if (arguments.length === 3) {
3010
+ if (this.subscriptions[id] && this.subscriptions[id][method]) {
3011
+ this.subscriptions[id][method](data)
3012
+ }
3013
+ }
3014
+ else {
3015
+ if (this.subscriptions[id]) {
3016
+ this.subscriptions[id].forEach(fn => {
3017
+ fn(method)
3018
+ })
3019
+ }
2724
3020
  }
2725
3021
  }
2726
- subscribe (method, fn) {
2727
- if (!this.subscriptions[method]) {
2728
- this.subscriptions[method] = []
3022
+ subscribe (id, method, fn) {
3023
+ if (arguments.length === 3) {
3024
+ if (!this.subscriptions[id]) {
3025
+ this.subscriptions[id] = {}
3026
+ }
3027
+ if (!this.subscriptions[id][method]) {
3028
+ this.subscriptions[id][method] = fn
3029
+ }
3030
+ }
3031
+ else {
3032
+ if (!this.subscriptions[id]) {
3033
+ this.subscriptions[id] = []
3034
+ }
3035
+ this.subscriptions[id].push(method)
2729
3036
  }
2730
- this.subscriptions[method].push(fn)
2731
3037
  }
2732
3038
  }
2733
3039
 
@@ -3724,6 +4030,55 @@ class WebsyRouter {
3724
4030
  }
3725
4031
  }
3726
4032
 
4033
+ class WebsySearch {
4034
+ constructor (elementId, options) {
4035
+ this.elementId = elementId
4036
+ const DEFAULTS = {
4037
+ searchIcon: `<svg class='search' width="20" height="20" viewBox="0 0 512 512"><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>`,
4038
+ clearIcon: `<svg class='clear' xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 512 512"><title>ionicons-v5-l</title><line x1="368" y1="368" x2="144" y2="144" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="368" y1="144" x2="144" y2="368" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>`,
4039
+ placeholder: 'Search',
4040
+ searchTimeout: 500,
4041
+ minLength: 2
4042
+ }
4043
+ this.options = Object.assign({}, DEFAULTS, options)
4044
+ this.searchTimeoutFn = null
4045
+ const el = document.getElementById(elementId)
4046
+ if (el) {
4047
+ // el.addEventListener('click', this.handleClick.bind(this))
4048
+ el.addEventListener('keyup', this.handleKeyUp.bind(this))
4049
+ el.innerHTML = `
4050
+ <div class='websy-search-input-container'>
4051
+ ${this.options.searchIcon}
4052
+ <input id='${this.elementId}_search' class='websy-search-input' placeholder='${this.options.placeholder || 'Search'}'>
4053
+ ${this.options.clearIcon}
4054
+ </div>
4055
+ `
4056
+ }
4057
+ else {
4058
+ console.log('No element found with Id', elementId)
4059
+ }
4060
+ }
4061
+ handleKeyUp (event) {
4062
+ if (event.target.classList.contains('websy-search-input')) {
4063
+ if (this.searchTimeoutFn) {
4064
+ clearTimeout(this.searchTimeoutFn)
4065
+ }
4066
+ if (event.target.value.length >= this.options.minLength) {
4067
+ this.searchTimeoutFn = setTimeout(() => {
4068
+ if (this.options.onSearch) {
4069
+ this.options.onSearch(event.target.value)
4070
+ }
4071
+ }, this.options.searchTimeout)
4072
+ }
4073
+ else {
4074
+ if (this.options.onSearch) {
4075
+ this.options.onSearch('')
4076
+ }
4077
+ }
4078
+ }
4079
+ }
4080
+ }
4081
+
3727
4082
  /* global WebsyDesigns ENVIRONMENT */
3728
4083
  class WebsySignup {
3729
4084
  constructor (elementId, options) {
@@ -3999,6 +4354,7 @@ const WebsyUtils = {
3999
4354
  let red = 0
4000
4355
  let green = 0
4001
4356
  let blue = 0
4357
+ let alpha = 1
4002
4358
  if (backgroundColor.indexOf('#') !== -1) {
4003
4359
  // hex color
4004
4360
  backgroundColor = backgroundColor.replace('#', '')
@@ -4010,13 +4366,15 @@ const WebsyUtils = {
4010
4366
  }
4011
4367
  else if (backgroundColor.toLowerCase().indexOf('rgb') !== -1) {
4012
4368
  // rgb color
4013
- colorParts = backgroundColor.replace(/rgb\(/gi, '').replace(/\)/gi, '')
4369
+ colorParts = backgroundColor.replace(/rgba\(/gi, '').replace(/\)/gi, '')
4370
+ colorParts = colorParts.replace(/rgb\(/gi, '')
4014
4371
  colorParts = colorParts.split(',')
4015
4372
  red = colorParts[0]
4016
4373
  green = colorParts[1]
4017
4374
  blue = colorParts[2]
4375
+ alpha = colorParts[3] || 1
4018
4376
  }
4019
- return (red * 0.299 + green * 0.587 + blue * 0.114) > 186 ? darkColor : lightColor
4377
+ return ((red * 0.299 + green * 0.587 + blue * 0.114) / alpha) > 186 ? darkColor : lightColor
4020
4378
  },
4021
4379
  measureText (text, rotation = 0, fontSize = '12px') {
4022
4380
  if (!isNaN(fontSize)) {
@@ -4466,8 +4824,15 @@ class WebsyTable {
4466
4824
  }
4467
4825
  let headHTML = '<tr>' + this.options.columns.map((c, i) => {
4468
4826
  if (c.show !== false) {
4827
+ let style = ''
4828
+ if (c.style) {
4829
+ style += c.style
4830
+ }
4831
+ if (c.width) {
4832
+ style += `width: ${(c.width || 'auto')};`
4833
+ }
4469
4834
  return `
4470
- <th ${c.width ? 'style="width: ' + (c.width || 'auto') + ';"' : ''}>
4835
+ <th style="${style}">
4471
4836
  <div class ="tableHeader">
4472
4837
  <div class="leftSection">
4473
4838
  <div
@@ -4881,7 +5246,12 @@ class WebsyTable2 {
4881
5246
  }
4882
5247
  }
4883
5248
  hideLoading () {
4884
- this.loadingDialog.hide()
5249
+ if (this.options.onLoading) {
5250
+ this.options.onLoading(false)
5251
+ }
5252
+ else {
5253
+ this.loadingDialog.hide()
5254
+ }
4885
5255
  }
4886
5256
  internalSort (column, colIndex) {
4887
5257
  this.options.columns.forEach((c, i) => {
@@ -4956,7 +5326,8 @@ class WebsyTable2 {
4956
5326
  class="tableHeaderField ${['asc', 'desc'].indexOf(c.sort) !== -1 ? 'sortable-column' : ''}"
4957
5327
  data-sort-index="${c.sortIndex || i}"
4958
5328
  data-index="${i}"
4959
- data-sort="${c.sort}"
5329
+ data-sort="${c.sort}"
5330
+ style="${c.style || ''}"
4960
5331
  >
4961
5332
  ${c.name}
4962
5333
  </div>
@@ -5058,7 +5429,12 @@ class WebsyTable2 {
5058
5429
  }
5059
5430
  }
5060
5431
  showLoading (options) {
5061
- this.loadingDialog.show(options)
5432
+ if (this.options.onLoading) {
5433
+ this.options.onLoading(true)
5434
+ }
5435
+ else {
5436
+ this.loadingDialog.show(options)
5437
+ }
5062
5438
  }
5063
5439
  getColumnParameters (values) {
5064
5440
  const tableEl = document.getElementById(`${this.elementId}_table`)
@@ -5122,6 +5498,603 @@ class WebsyTable2 {
5122
5498
  }
5123
5499
  }
5124
5500
 
5501
+ /* global WebsyDesigns */
5502
+ class WebsyTable3 {
5503
+ constructor (elementId, options) {
5504
+ this.elementId = elementId
5505
+ const DEFAULTS = {
5506
+ virtualScroll: false,
5507
+ showTotalsAbove: true,
5508
+ minHandleSize: 20,
5509
+ maxColWidth: '50%',
5510
+ allowPivoting: false,
5511
+ 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>`
5512
+ }
5513
+ this.options = Object.assign({}, DEFAULTS, options)
5514
+ this.sizes = {}
5515
+ this.scrollDragging = false
5516
+ this.cellDragging = false
5517
+ this.vScrollRequired = false
5518
+ this.hScrollRequired = false
5519
+ this.pinnedColumns = 0
5520
+ this.startRow = 0
5521
+ this.endRow = 0
5522
+ this.startCol = 0
5523
+ this.endCol = 0
5524
+ this.mouseYStart = 0
5525
+ this.mouseYStart = 0
5526
+ if (!elementId) {
5527
+ console.log('No element Id provided for Websy Table')
5528
+ return
5529
+ }
5530
+ const el = document.getElementById(this.elementId)
5531
+ if (el) {
5532
+ let html = `
5533
+ <div id='${this.elementId}_tableContainer' class='websy-vis-table-3 ${this.options.paging === 'pages' ? 'with-paging' : ''} ${this.options.virtualScroll === true ? 'with-virtual-scroll' : ''}'>
5534
+ <!--<div class="download-button">
5535
+ <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>
5536
+ </div>-->
5537
+ <div id="${this.elementId}_tableInner" class="websy-table-inner-container">
5538
+ <table id="${this.elementId}_tableHeader" class="websy-table-header"></table>
5539
+ <table id="${this.elementId}_tableBody" class="websy-table-body"></table>
5540
+ <table id="${this.elementId}_tableFooter" class="websy-table-footer"></table>
5541
+ <div id="${this.elementId}_vScrollContainer" class="websy-v-scroll-container">
5542
+ <div id="${this.elementId}_vScrollHandle" class="websy-scroll-handle websy-scroll-handle-y"></div>
5543
+ </div>
5544
+ <div id="${this.elementId}_hScrollContainer" class="websy-h-scroll-container">
5545
+ <div id="${this.elementId}_hScrollHandle" class="websy-scroll-handle websy-scroll-handle-x"></div>
5546
+ </div>
5547
+ </div>
5548
+ <div id="${this.elementId}_errorContainer" class='websy-vis-error-container'>
5549
+ <div>
5550
+ <div id="${this.elementId}_errorTitle"></div>
5551
+ <div id="${this.elementId}_errorMessage"></div>
5552
+ </div>
5553
+ </div>
5554
+ <div id="${this.elementId}_dropdownContainer"></div>
5555
+ <div id="${this.elementId}_loadingContainer"></div>
5556
+ </div>
5557
+ `
5558
+ if (this.options.paging === 'pages') {
5559
+ html += `
5560
+ <div class="websy-table-paging-container">
5561
+ Show <div id="${this.elementId}_pageSizeSelector" class="websy-vis-page-selector"></div> rows
5562
+ <ul id="${this.elementId}_pageList" class="websy-vis-page-list"></ul>
5563
+ </div>
5564
+ `
5565
+ }
5566
+ el.innerHTML = html
5567
+ el.addEventListener('click', this.handleClick.bind(this))
5568
+ el.addEventListener('mousedown', this.handleMouseDown.bind(this))
5569
+ window.addEventListener('mousemove', this.handleMouseMove.bind(this))
5570
+ window.addEventListener('mouseup', this.handleMouseUp.bind(this))
5571
+ let scrollEl = document.getElementById(`${this.elementId}_tableBody`)
5572
+ if (scrollEl) {
5573
+ scrollEl.addEventListener('wheel', this.handleScrollWheel.bind(this))
5574
+ }
5575
+ this.loadingDialog = new WebsyDesigns.LoadingDialog(`${this.elementId}_loadingContainer`)
5576
+ this.render(this.options.data)
5577
+ }
5578
+ else {
5579
+ console.error(`No element found with ID ${this.elementId}`)
5580
+ }
5581
+ }
5582
+ set columns (columns) {
5583
+ this.options.columns = columns
5584
+ this.renderColumnHeaders()
5585
+ }
5586
+ set totals (totals) {
5587
+ this.options.totals = totals
5588
+ this.renderTotals()
5589
+ }
5590
+ appendRows (data) {
5591
+ this.hideError()
5592
+ let bodyEl = document.getElementById(`${this.elementId}_tableBody`)
5593
+ if (bodyEl) {
5594
+ if (this.options.virtualScroll === true) {
5595
+ bodyEl.innerHTML = this.buildBodyHtml(data, true)
5596
+ }
5597
+ else {
5598
+ bodyEl.innerHTML += this.buildBodyHtml(data, true)
5599
+ }
5600
+ }
5601
+ // this.data = this.data.concat(data)
5602
+ // this.rowCount = this.data.length
5603
+ }
5604
+ buildBodyHtml (data = [], useWidths = false) {
5605
+ if (data.length === 0) {
5606
+ return ''
5607
+ }
5608
+ let bodyHtml = ``
5609
+ let sizingColumns = this.options.columns[this.options.columns.length - 1]
5610
+ if (useWidths === true) {
5611
+ bodyHtml += '<colgroup>'
5612
+ bodyHtml += sizingColumns.map(c => `
5613
+ <col
5614
+ style='width: ${c.width || c.actualWidth}px!important'
5615
+ ></col>
5616
+ `).join('')
5617
+ bodyHtml += '</colgroup>'
5618
+ }
5619
+ data.forEach(row => {
5620
+ bodyHtml += `<tr class="websy-table-row">`
5621
+ row.forEach((cell, cellIndex) => {
5622
+ let style = ''
5623
+ if (cell.style) {
5624
+ style += cell.style
5625
+ }
5626
+ if (cell.backgroundColor) {
5627
+ style += `background-color: ${cell.backgroundColor}; `
5628
+ if (!cell.color) {
5629
+ style += `color: ${WebsyDesigns.Utils.getLightDark(cell.backgroundColor)}; `
5630
+ }
5631
+ }
5632
+ if (cell.color) {
5633
+ style += `color: ${cell.color}; `
5634
+ }
5635
+ bodyHtml += `<td
5636
+ class='websy-table-cell'
5637
+ style='${style}'
5638
+ data-info='${cell.value}'
5639
+ colspan='${cell.colspan || 1}'
5640
+ rowspan='${cell.rowspan || 1}'
5641
+ `
5642
+ // if (useWidths === true) {
5643
+ // bodyHtml += `
5644
+ // style='width: ${sizingColumns[cellIndex].width || sizingColumns[cellIndex].actualWidth}px!important'
5645
+ // width='${sizingColumns[cellIndex].width || sizingColumns[cellIndex].actualWidth}'
5646
+ // `
5647
+ // }
5648
+ bodyHtml += `
5649
+ >
5650
+ ${cell.value}
5651
+ </td>`
5652
+ })
5653
+ bodyHtml += `</tr>`
5654
+ })
5655
+ // bodyHtml += `</div>`
5656
+ return bodyHtml
5657
+ }
5658
+ buildHeaderHtml (useWidths = false) {
5659
+ let headerHtml = ''
5660
+ let sizingColumns = this.options.columns[this.options.columns.length - 1]
5661
+ if (useWidths === true) {
5662
+ headerHtml += '<colgroup>'
5663
+ headerHtml += sizingColumns.map(c => `
5664
+ <col
5665
+ style='width: ${c.width || c.actualWidth}px!important'
5666
+ ></col>
5667
+ `).join('')
5668
+ headerHtml += '</colgroup>'
5669
+ }
5670
+ this.options.columns.forEach((row, rowIndex) => {
5671
+ if (useWidths === false && rowIndex !== this.options.columns.length - 1) {
5672
+ // if we're calculating the size we only want to render the last row of column headers
5673
+ return
5674
+ }
5675
+ headerHtml += `<tr class="websy-table-row websy-table-header-row">`
5676
+ row.forEach((col, colIndex) => {
5677
+ headerHtml += `<td
5678
+ class='websy-table-cell'
5679
+ style='${col.style}'
5680
+ colspan='${col.colspan || 1}'
5681
+ rowspan='${col.rowspan || 1}'
5682
+ `
5683
+ // if (useWidths === true && rowIndex === this.options.columns.length - 1) {
5684
+ // headerHtml += `
5685
+ // style='width: ${col.width || col.actualWidth}px'
5686
+ // width='${col.width || col.actualWidth}'
5687
+ // `
5688
+ // }
5689
+ headerHtml += `
5690
+ >
5691
+ <div>
5692
+ ${col.name}
5693
+ ${col.searchable === true ? this.buildSearchIcon(col, colIndex) : ''}
5694
+ </div>
5695
+ </td>`
5696
+ })
5697
+ headerHtml += `</tr>`
5698
+ })
5699
+ const dropdownEl = document.getElementById(`${this.elementId}_dropdownContainer`)
5700
+ this.options.columns[this.options.columns.length - 1].forEach((c, i) => {
5701
+ if (c.searchable && c.isExternalSearch === true) {
5702
+ const testEl = document.getElementById(`${this.elementId}_columnSearch_${c.dimId || i}`)
5703
+ if (!testEl) {
5704
+ const newE = document.createElement('div')
5705
+ newE.id = `${this.elementId}_columnSearch_${c.dimId || i}`
5706
+ newE.className = 'websy-modal-dropdown'
5707
+ dropdownEl.appendChild(newE)
5708
+ }
5709
+ }
5710
+ })
5711
+ return headerHtml
5712
+ }
5713
+ buildSearchIcon (col, index) {
5714
+ return `
5715
+ <div class="websy-table-search-icon" data-col-id="${col.dimId}" data-col-index="${index}">
5716
+ <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>
5717
+ </div>
5718
+ `
5719
+ }
5720
+ buildTotalHtml (useWidths = false) {
5721
+ if (!this.options.totals) {
5722
+ return ''
5723
+ }
5724
+ let totalHtml = `<tr class="websy-table-row websy-table-total-row">`
5725
+ this.options.totals.forEach((col, colIndex) => {
5726
+ totalHtml += `<td
5727
+ class='websy-table-cell'
5728
+ colspan='${col.colspan || 1}'
5729
+ rowspan='${col.rowspan || 1}'
5730
+ `
5731
+ if (useWidths === true) {
5732
+ totalHtml += `
5733
+ style='width: ${this.options.columns[this.options.columns.length - 1][colIndex].width || this.options.columns[this.options.columns.length - 1][colIndex].actualWidth}px'
5734
+ width='${col.width || col.actualWidth}'
5735
+ `
5736
+ }
5737
+ totalHtml += `
5738
+ >
5739
+ ${col.value}
5740
+ </td>`
5741
+ })
5742
+ totalHtml += `</tr>`
5743
+ return totalHtml
5744
+ }
5745
+ calculateSizes (sample = [], totalRowCount, totalColumnCount, pinnedColumns) {
5746
+ this.totalRowCount = totalRowCount // probably need some error handling here if no value is passed in
5747
+ this.totalColumnCount = totalColumnCount // probably need some error handling here if no value is passed in
5748
+ this.pinnedColumns = pinnedColumns // probably need some error handling here if no value is passed in
5749
+ let outerEl = document.getElementById(this.elementId)
5750
+ let tableEl = document.getElementById(`${this.elementId}_tableContainer`)
5751
+ let headEl = document.getElementById(`${this.elementId}_tableHeader`)
5752
+ headEl.style.width = 'auto'
5753
+ headEl.innerHTML = this.buildHeaderHtml()
5754
+ this.sizes.outer = outerEl.getBoundingClientRect()
5755
+ this.sizes.table = tableEl.getBoundingClientRect()
5756
+ this.sizes.header = headEl.getBoundingClientRect()
5757
+ let maxWidth
5758
+ if (typeof this.options.maxColWidth === 'number') {
5759
+ maxWidth = this.options.maxColWidth
5760
+ }
5761
+ else if (this.options.maxColWidth.indexOf('%') !== -1) {
5762
+ maxWidth = this.sizes.outer.width * (+(this.options.maxColWidth.replace('%', '')) / 100)
5763
+ }
5764
+ else if (this.options.maxColWidth.indexOf('px') !== -1) {
5765
+ maxWidth = +this.options.maxColWidth.replace('px', '')
5766
+ }
5767
+ let bodyEl = document.getElementById(`${this.elementId}_tableBody`)
5768
+ bodyEl.style.width = 'auto'
5769
+ bodyEl.innerHTML = this.buildBodyHtml([sample])
5770
+ let footerEl = document.getElementById(`${this.elementId}_tableFooter`)
5771
+ footerEl.innerHTML = this.buildTotalHtml()
5772
+ this.sizes.total = footerEl.getBoundingClientRect()
5773
+ const rows = Array.from(tableEl.querySelectorAll('.websy-table-row'))
5774
+ let totalWidth = 0
5775
+ this.sizes.scrollableWidth = this.sizes.outer.width
5776
+ rows.forEach((row, rowIndex) => {
5777
+ Array.from(row.children).forEach((col, colIndex) => {
5778
+ let colSize = col.getBoundingClientRect()
5779
+ this.sizes.cellHeight = colSize.height
5780
+ if (this.options.columns[this.options.columns.length - 1][colIndex]) {
5781
+ if (!this.options.columns[this.options.columns.length - 1][colIndex].actualWidth) {
5782
+ this.options.columns[this.options.columns.length - 1][colIndex].actualWidth = 0
5783
+ }
5784
+ 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)
5785
+ this.options.columns[this.options.columns.length - 1][colIndex].cellHeight = colSize.height
5786
+ }
5787
+ })
5788
+ })
5789
+ this.options.columns[this.options.columns.length - 1].forEach((col, colIndex) => {
5790
+ if (colIndex < this.pinnedColumns) {
5791
+ this.sizes.scrollableWidth -= col.actualWidth
5792
+ }
5793
+ })
5794
+ this.sizes.totalWidth = this.options.columns[this.options.columns.length - 1].reduce((a, b) => a + (b.width || b.actualWidth), 0)
5795
+ const outerSize = outerEl.getBoundingClientRect()
5796
+ if (this.sizes.totalWidth < outerSize.width) {
5797
+ this.sizes.totalWidth = 0
5798
+ let equalWidth = outerSize.width / this.options.columns[this.options.columns.length - 1].length
5799
+ this.options.columns[this.options.columns.length - 1].forEach((c, i) => {
5800
+ if (!c.width) {
5801
+ if (c.actualWidth < equalWidth) {
5802
+ // adjust the width
5803
+ c.actualWidth = equalWidth
5804
+ }
5805
+ }
5806
+ this.sizes.totalWidth += c.width || c.actualWidth
5807
+ equalWidth = (outerSize.width - this.sizes.totalWidth) / (this.options.columns[this.options.columns.length - 1].length - (i + 1))
5808
+ })
5809
+ }
5810
+ // take the height of the last cell as the official height for data cells
5811
+ // this.sizes.dataCellHeight = this.options.columns[this.options.columns.length - 1].cellHeight
5812
+ headEl.innerHTML = ''
5813
+ bodyEl.innerHTML = ''
5814
+ footerEl.innerHTML = ''
5815
+ headEl.style.width = 'initial'
5816
+ bodyEl.style.width = 'initial'
5817
+ this.sizes.bodyHeight = this.sizes.table.height - (this.sizes.header.height + this.sizes.total.height)
5818
+ this.sizes.rowsToRender = Math.ceil(this.sizes.bodyHeight / this.sizes.cellHeight)
5819
+ this.sizes.rowsToRenderPrecise = this.sizes.bodyHeight / this.sizes.cellHeight
5820
+ this.startRow = 0
5821
+ this.endRow = this.sizes.rowsToRender
5822
+ this.startCol = 0
5823
+ this.endCol = this.options.columns[this.options.columns.length - 1].length
5824
+ if (this.sizes.rowsToRender < this.totalRowCount) {
5825
+ this.vScrollRequired = true
5826
+ }
5827
+ if (this.sizes.totalWidth > this.sizes.outer.width) {
5828
+ this.hScrollRequired = true
5829
+ }
5830
+ this.options.allColumns = this.options.columns.map(c => c)
5831
+ console.log('sizes', this.sizes)
5832
+ return this.sizes
5833
+ }
5834
+ createSample (data) {
5835
+ let output = []
5836
+ this.options.columns[this.options.columns.length - 1].forEach((col, colIndex) => {
5837
+ if (col.maxLength) {
5838
+ output.push({value: new Array(col.maxLength).fill('W').join('')})
5839
+ }
5840
+ else if (data) {
5841
+ let longest = ''
5842
+ for (let i = 0; i < Math.min(data.length, 1000); i++) {
5843
+ if (longest.length < data[i][colIndex].value.length) {
5844
+ longest = data[i][colIndex].value
5845
+ }
5846
+ }
5847
+ output.push({value: longest})
5848
+ }
5849
+ else {
5850
+ output.push({value: ''})
5851
+ }
5852
+ })
5853
+ return output
5854
+ }
5855
+ handleClick (event) {
5856
+ if (event.target.classList.contains('websy-table-search-icon')) {
5857
+ console.log('clicked on search icon')
5858
+ const colIndex = +event.target.getAttribute('data-col-index')
5859
+ if (this.options.columns[this.options.columns.length - 1][colIndex].onSearch) {
5860
+ this.options.columns[this.options.columns.length - 1][colIndex].onSearch(event, this.options.columns[this.options.columns.length - 1][colIndex])
5861
+ }
5862
+ }
5863
+ }
5864
+ handleMouseDown (event) {
5865
+ if (event.target.classList.contains('websy-scroll-handle-y')) {
5866
+ // set up the scroll start values
5867
+ this.scrollDragging = true
5868
+ this.scrollDirection = 'y'
5869
+ const scrollHandleEl = document.getElementById(`${this.elementId}_vScrollHandle`)
5870
+ this.handleYStart = scrollHandleEl.offsetTop
5871
+ this.mouseYStart = event.pageY
5872
+ console.log('mouse down', this.handleYStart, this.mouseYStart)
5873
+ console.log(scrollHandleEl.offsetTop)
5874
+ }
5875
+ else if (event.target.classList.contains('websy-scroll-handle-x')) {
5876
+ this.scrollDragging = true
5877
+ this.scrollDirection = 'x'
5878
+ const scrollHandleEl = document.getElementById(`${this.elementId}_hScrollHandle`)
5879
+ this.handleXStart = scrollHandleEl.offsetLeft
5880
+ this.mouseXStart = event.pageX
5881
+ }
5882
+ }
5883
+ handleMouseMove (event) {
5884
+ // event.preventDefault()
5885
+ if (this.scrollDragging === true) {
5886
+ if (this.scrollDirection === 'y') {
5887
+ const diff = event.pageY - this.mouseYStart
5888
+ this.scrollY(diff)
5889
+ }
5890
+ else if (this.scrollDirection === 'x') {
5891
+ const diff = event.pageX - this.mouseXStart
5892
+ this.scrollX(diff)
5893
+ }
5894
+ }
5895
+ }
5896
+ handleMouseUp (event) {
5897
+ this.scrollDragging = false
5898
+ this.cellDragging = false
5899
+ this.handleYStart = null
5900
+ this.mouseYStart = null
5901
+ this.handleXStart = null
5902
+ this.mouseXStart = null
5903
+ }
5904
+ handleScrollWheel (event) {
5905
+ event.preventDefault()
5906
+ console.log('scrollwheel', event)
5907
+ if (Math.abs(event.deltaX) > Math.abs(event.deltaY)) {
5908
+ this.scrollX(Math.max(-5, Math.min(5, event.deltaX)))
5909
+ }
5910
+ else {
5911
+ this.scrollY(Math.max(-5, Math.min(5, event.deltaY)))
5912
+ }
5913
+ }
5914
+ hideError () {
5915
+ const el = document.getElementById(`${this.elementId}_tableContainer`)
5916
+ if (el) {
5917
+ el.classList.remove('has-error')
5918
+ }
5919
+ const tableEl = document.getElementById(`${this.elementId}_tableInner`)
5920
+ tableEl.classList.remove('hidden')
5921
+ const containerEl = document.getElementById(`${this.elementId}_errorContainer`)
5922
+ if (containerEl) {
5923
+ containerEl.classList.remove('active')
5924
+ }
5925
+ }
5926
+ hideLoading () {
5927
+ this.loadingDialog.hide()
5928
+ }
5929
+ render (data, calcSizes = true) {
5930
+ if (!this.options.columns) {
5931
+ console.log(`No columns provided for table with ID ${this.elementId}`)
5932
+ return
5933
+ }
5934
+ if (this.options.columns.length === 0) {
5935
+ console.log(`No columns provided for table with ID ${this.elementId}`)
5936
+ return
5937
+ }
5938
+ // this.data = []
5939
+ // Adjust the sizing of the header/body/footer
5940
+ if (calcSizes === true) {
5941
+ const sample = this.createSample(data)
5942
+ this.calculateSizes(sample, data.length, (data[0] || []).length, 0)
5943
+ }
5944
+ console.log(this.options.columns)
5945
+ const tableInnerEl = document.getElementById(`${this.elementId}_tableInner`)
5946
+ if (tableInnerEl) {
5947
+ tableInnerEl.style.width = `${this.sizes.totalWidth}px`
5948
+ }
5949
+ this.renderColumnHeaders()
5950
+ this.renderTotals()
5951
+ if (data) {
5952
+ this.appendRows(data)
5953
+ }
5954
+ let bodyEl = document.getElementById(`${this.elementId}_tableBody`)
5955
+ // bodyEl.innerHTML = this.buildBodyHtml(data, true)
5956
+ bodyEl.style.height = `calc(100% - ${this.sizes.header.height}px - ${this.sizes.total.height}px)`
5957
+ if (this.options.virtualScroll === true) {
5958
+ // set the scroll element positions
5959
+ let vScrollEl = document.getElementById(`${this.elementId}_vScrollContainer`)
5960
+ let vHandleEl = document.getElementById(`${this.elementId}_vScrollHandle`)
5961
+ if (this.vScrollRequired === true) {
5962
+ vScrollEl.style.top = `${this.sizes.header.height + this.sizes.total.height}px`
5963
+ vScrollEl.style.height = `${this.sizes.bodyHeight}px`
5964
+ vHandleEl.style.height = Math.max(this.options.minHandleSize, this.sizes.bodyHeight * (this.sizes.rowsToRenderPrecise / this.totalRowCount)) + 'px'
5965
+ }
5966
+ else {
5967
+ vHandleEl.style.height = '0px'
5968
+ }
5969
+ let hScrollEl = document.getElementById(`${this.elementId}_hScrollContainer`)
5970
+ let hHandleEl = document.getElementById(`${this.elementId}_hScrollHandle`)
5971
+ if (this.hScrollRequired === true) {
5972
+ hScrollEl.style.left = `${this.sizes.table.width - this.sizes.scrollableWidth}px`
5973
+ hScrollEl.style.width = `${this.sizes.scrollableWidth - 20}px`
5974
+ hHandleEl.style.width = Math.max(this.options.minHandleSize, this.sizes.scrollableWidth * (this.sizes.scrollableWidth / this.sizes.totalWidth)) + 'px'
5975
+ }
5976
+ else {
5977
+ hHandleEl.style.height = '0px'
5978
+ }
5979
+ }
5980
+ }
5981
+ renderColumnHeaders () {
5982
+ let headEl = document.getElementById(`${this.elementId}_tableHeader`)
5983
+ if (headEl) {
5984
+ headEl.innerHTML = this.buildHeaderHtml(true)
5985
+ }
5986
+ }
5987
+ renderTotals () {
5988
+ let headEl = document.getElementById(`${this.elementId}_tableHeader`)
5989
+ let totalHtml = this.buildTotalHtml(true)
5990
+ if (this.options.showTotalsAbove === true) {
5991
+ headEl.innerHTML += totalHtml
5992
+ }
5993
+ else {
5994
+ const footerEl = document.getElementById(`${this.elementId}_tableFooter`)
5995
+ if (footerEl) {
5996
+ footerEl.innerHTML = totalHtml
5997
+ }
5998
+ }
5999
+ }
6000
+ resize () {
6001
+
6002
+ }
6003
+ showError (options) {
6004
+ const el = document.getElementById(`${this.elementId}_tableContainer`)
6005
+ if (el) {
6006
+ el.classList.add('has-error')
6007
+ }
6008
+ const tableEl = document.getElementById(`${this.elementId}_tableInner`)
6009
+ tableEl.classList.add('hidden')
6010
+ const containerEl = document.getElementById(`${this.elementId}_errorContainer`)
6011
+ if (containerEl) {
6012
+ containerEl.classList.add('active')
6013
+ }
6014
+ if (options.title) {
6015
+ const titleEl = document.getElementById(`${this.elementId}_errorTitle`)
6016
+ if (titleEl) {
6017
+ titleEl.innerHTML = options.title
6018
+ }
6019
+ }
6020
+ if (options.message) {
6021
+ const messageEl = document.getElementById(`${this.elementId}_errorMessage`)
6022
+ if (messageEl) {
6023
+ messageEl.innerHTML = options.message
6024
+ }
6025
+ }
6026
+ }
6027
+ scrollX (diff) {
6028
+ const scrollContainerEl = document.getElementById(`${this.elementId}_hScrollContainer`)
6029
+ const scrollHandleEl = document.getElementById(`${this.elementId}_hScrollHandle`)
6030
+ let handlePos
6031
+ if (typeof this.handleXStart !== 'undefined' && this.handleXStart !== null) {
6032
+ handlePos = this.handleXStart + diff
6033
+ }
6034
+ else {
6035
+ handlePos = scrollHandleEl.offsetLeft + diff
6036
+ }
6037
+ const scrollableSpace = scrollContainerEl.getBoundingClientRect().width - scrollHandleEl.getBoundingClientRect().width
6038
+ console.log('dragging x', diff, scrollContainerEl.getBoundingClientRect().width - scrollHandleEl.getBoundingClientRect().width)
6039
+ scrollHandleEl.style.left = Math.min(scrollableSpace, Math.max(0, handlePos)) + 'px'
6040
+ if (this.options.onScroll) {
6041
+ let actualLeft = (this.sizes.totalWidth - this.sizes.scrollableWidth) * (Math.min(scrollableSpace, Math.max(0, handlePos)) / scrollableSpace)
6042
+ let cumulativeWidth = 0
6043
+ this.startCol = 0
6044
+ this.endCol = 0
6045
+ for (let i = 0; i < this.options.allColumns[this.options.allColumns.length - 1].length; i++) {
6046
+ cumulativeWidth += this.options.allColumns[this.options.allColumns.length - 1][i].actualWidth
6047
+ console.log('actualLeft', actualLeft, this.sizes.totalWidth, cumulativeWidth, cumulativeWidth + this.options.allColumns[this.options.allColumns.length - 1][i].actualWidth)
6048
+ if (actualLeft < cumulativeWidth) {
6049
+ this.startCol = i
6050
+ break
6051
+ }
6052
+ }
6053
+ cumulativeWidth = 0
6054
+ for (let i = this.startCol; i < this.options.allColumns[this.options.allColumns.length - 1].length; i++) {
6055
+ cumulativeWidth += this.options.allColumns[this.options.allColumns.length - 1][i].actualWidth
6056
+ if (cumulativeWidth < this.sizes.scrollableWidth) {
6057
+ this.endCol = i
6058
+ }
6059
+ }
6060
+ if (this.endCol < this.options.allColumns[this.options.allColumns.length - 1].length - 1) {
6061
+ this.endCol += 1
6062
+ }
6063
+ if (this.endCol === this.options.allColumns[this.options.allColumns.length - 1].length - 1 && cumulativeWidth > this.sizes.totalWidth) {
6064
+ this.startCol += 1
6065
+ }
6066
+ this.endCol = Math.max(this.startCol, this.endCol)
6067
+ this.options.onScroll('y', this.startRow, this.endRow, this.startCol, this.endCol)
6068
+ }
6069
+ }
6070
+ scrollY (diff) {
6071
+ const scrollContainerEl = document.getElementById(`${this.elementId}_vScrollContainer`)
6072
+ const scrollHandleEl = document.getElementById(`${this.elementId}_vScrollHandle`)
6073
+ let handlePos
6074
+ if (typeof this.handleYStart !== 'undefined' && this.handleYStart !== null) {
6075
+ handlePos = this.handleYStart + diff
6076
+ }
6077
+ else {
6078
+ console.log('appending not resetting')
6079
+ handlePos = scrollHandleEl.offsetTop + diff
6080
+ }
6081
+ const scrollableSpace = scrollContainerEl.getBoundingClientRect().height - scrollHandleEl.getBoundingClientRect().height
6082
+ console.log('dragging y', (diff), scrollContainerEl.getBoundingClientRect().height - scrollHandleEl.getBoundingClientRect().height)
6083
+ scrollHandleEl.style.top = Math.min(scrollableSpace, Math.max(0, handlePos)) + 'px'
6084
+ if (this.options.onScroll) {
6085
+ this.startRow = Math.min(this.totalRowCount - this.sizes.rowsToRender, Math.max(0, Math.round((this.totalRowCount - this.sizes.rowsToRender) * (handlePos / scrollableSpace))))
6086
+ this.endRow = this.startRow + this.sizes.rowsToRender
6087
+ if (this.endRow === this.totalRowCount) {
6088
+ this.startRow += 1
6089
+ }
6090
+ this.options.onScroll('y', this.startRow, this.endRow, this.startCol, this.endCol)
6091
+ }
6092
+ }
6093
+ showLoading (options) {
6094
+ this.loadingDialog.show(options)
6095
+ }
6096
+ }
6097
+
5125
6098
  /* global d3 include WebsyDesigns */
5126
6099
  class WebsyChart {
5127
6100
  constructor (elementId, options) {
@@ -6046,7 +7019,7 @@ bars
6046
7019
  .attr('x', getBarX.bind(this))
6047
7020
  .attr('y', getBarY.bind(this))
6048
7021
  .transition(this.transition)
6049
- .attr('fill', series.color)
7022
+ .attr('fill', d => d.color || series.color)
6050
7023
 
6051
7024
  bars
6052
7025
  .enter()
@@ -6056,7 +7029,7 @@ bars
6056
7029
  .attr('x', getBarX.bind(this))
6057
7030
  .attr('y', getBarY.bind(this))
6058
7031
  // .transition(this.transition)
6059
- .attr('fill', series.color)
7032
+ .attr('fill', d => d.color || series.color)
6060
7033
  .attr('class', d => {
6061
7034
  return `bar bar_${series.key}`
6062
7035
  })
@@ -6086,7 +7059,7 @@ if (this.options.showLabels) {
6086
7059
  .attr('y', getLabelY.bind(this))
6087
7060
  .attr('class', `label_${series.key}`)
6088
7061
  .style('font-size', `${this.options.labelSize || this.options.fontSize}px`)
6089
- .style('fill', this.options.labelColor || WebsyDesigns.WebsyUtils.getLightDark(series.color))
7062
+ .style('fill', d => this.options.labelColor || WebsyDesigns.WebsyUtils.getLightDark(d.color || series.color))
6090
7063
  .transition(this.transition)
6091
7064
  .text(d => d.y.label || d.y.value)
6092
7065
 
@@ -6099,7 +7072,7 @@ if (this.options.showLabels) {
6099
7072
  .attr('alignment-baseline', 'central')
6100
7073
  .attr('text-anchor', this.options.orientation === 'horizontal' ? 'left' : 'middle')
6101
7074
  .style('font-size', `${this.options.labelSize || this.options.fontSize}px`)
6102
- .style('fill', this.options.labelColor || WebsyDesigns.WebsyUtils.getLightDark(series.color))
7075
+ .style('fill', d => this.options.labelColor || WebsyDesigns.WebsyUtils.getLightDark(d.color || series.color))
6103
7076
  .text(d => d.y.label || d.y.value)
6104
7077
  .each(function (d, i) {
6105
7078
  if (that.options.orientation === 'horizontal') {
@@ -6805,8 +7778,10 @@ const WebsyDesigns = {
6805
7778
  Router: WebsyRouter,
6806
7779
  WebsyTable,
6807
7780
  WebsyTable2,
7781
+ WebsyTable3,
6808
7782
  Table: WebsyTable,
6809
7783
  Table2: WebsyTable2,
7784
+ Table3: WebsyTable3,
6810
7785
  WebsyChart,
6811
7786
  Chart: WebsyChart,
6812
7787
  WebsyChartTooltip,
@@ -6833,7 +7808,11 @@ const WebsyDesigns = {
6833
7808
  WebsySignup,
6834
7809
  Signup: WebsySignup,
6835
7810
  ResponsiveText,
6836
- WebsyResponsiveText: ResponsiveText
7811
+ WebsyResponsiveText: ResponsiveText,
7812
+ WebsyDragDrop,
7813
+ DragDrop: WebsyDragDrop,
7814
+ WebsySearch,
7815
+ Search: WebsySearch
6837
7816
  }
6838
7817
 
6839
7818
  WebsyDesigns.service = new WebsyDesigns.APIService('')