@websy/websy-designs 1.2.33 → 1.3.1

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.
@@ -29,6 +29,7 @@
29
29
  WebsySignup
30
30
  ResponsiveText
31
31
  WebsyDragDrop
32
+ WebsySearch
32
33
  Pager
33
34
  */
34
35
 
@@ -561,6 +562,7 @@ class WebsyDatePicker {
561
562
  }
562
563
  }
563
564
  close (confirm, isRange = false) {
565
+ console.trace()
564
566
  const maskEl = document.getElementById(`${this.elementId}_mask`)
565
567
  const contentEl = document.getElementById(`${this.elementId}_content`)
566
568
  const el = document.getElementById(this.elementId)
@@ -577,19 +579,19 @@ class WebsyDatePicker {
577
579
  for (let i = this.selectedRangeDates[0]; i < this.selectedRangeDates[1] + 1; i++) {
578
580
  hoursOut.push(this.options.hours[i])
579
581
  }
580
- this.options.onChange(hoursOut, true)
582
+ this.options.onChange(hoursOut, true, this.selectedRange)
581
583
  }
582
584
  else {
583
- this.options.onChange(this.selectedRangeDates, true)
585
+ this.options.onChange(this.selectedRangeDates, true, this.selectedRange)
584
586
  }
585
587
  }
586
588
  else {
587
589
  if (this.options.mode === 'hour') {
588
590
  let hoursOut = this.currentselection.map(h => this.options.hours[h])
589
- this.options.onChange(hoursOut, true)
591
+ this.options.onChange(hoursOut, true, this.selectedRange)
590
592
  }
591
593
  else {
592
- this.options.onChange(this.currentselection, isRange)
594
+ this.options.onChange(this.currentselection, isRange, this.selectedRange)
593
595
  }
594
596
  }
595
597
  }
@@ -611,7 +613,8 @@ class WebsyDatePicker {
611
613
  if (typeof d === 'number') {
612
614
  d = new Date(d)
613
615
  }
614
- return new Date(d.setHours(0, 0, 0, 0))
616
+ // d.setTime(d.getTime() + d.getTimezoneOffset() * 60000)
617
+ return new Date(d.setUTCHours(12, 0, 0, 0))
615
618
  }
616
619
  handleClick (event) {
617
620
  if (event.target.classList.contains('websy-date-picker-header')) {
@@ -629,11 +632,7 @@ class WebsyDatePicker {
629
632
  this.updateRange(index)
630
633
  }
631
634
  else if (event.target.classList.contains('websy-dp-date')) {
632
- // if (event.target.classList.contains('websy-disabled-date')) {
633
- // return
634
- // }
635
- // const timestamp = event.target.id.split('_')[0]
636
- // this.selectDate(+timestamp)
635
+ //
637
636
  }
638
637
  else if (event.target.classList.contains('websy-dp-confirm')) {
639
638
  this.close(true)
@@ -662,7 +661,8 @@ class WebsyDatePicker {
662
661
  handleMouseDown (event) {
663
662
  if (this.shiftPressed === true && this.currentselection.length > 0) {
664
663
  this.mouseDownId = this.currentselection[this.currentselection.length - 1]
665
- this.selectDate(+event.target.id.split('_')[1])
664
+ let dateId = event.target.getAttribute('data-id')
665
+ this.selectDate(+dateId)
666
666
  }
667
667
  else {
668
668
  this.mouseDown = true
@@ -675,7 +675,7 @@ class WebsyDatePicker {
675
675
  this.currentselection = []
676
676
  this.customRangeSelected = false
677
677
  }
678
- this.mouseDownId = +event.target.id.split('_')[1]
678
+ this.mouseDownId = +event.target.getAttribute('data-id')
679
679
  this.selectDate(this.mouseDownId)
680
680
  }
681
681
  }
@@ -686,9 +686,10 @@ class WebsyDatePicker {
686
686
  if (event.target.classList.contains('websy-disabled-date')) {
687
687
  return
688
688
  }
689
- if (event.target.id.split('_')[1] !== this.mouseDownId) {
689
+ let dateId = +event.target.getAttribute('data-id')
690
+ if (dateId !== this.mouseDownId) {
690
691
  this.dragging = true
691
- this.selectDate(+event.target.id.split('_')[1])
692
+ this.selectDate(dateId)
692
693
  }
693
694
  }
694
695
  }
@@ -736,6 +737,7 @@ class WebsyDatePicker {
736
737
  let rangeEnd
737
738
  if (this.options.mode === 'date') {
738
739
  d = this.floorDate(new Date(this.selectedRangeDates[0].getTime() + (i * this.oneDay)))
740
+ d.setUTCHours(12, 0, 0, 0)
739
741
  d = d.getTime()
740
742
  rangeStart = this.selectedRangeDates[0].getTime()
741
743
  rangeEnd = this.selectedRangeDates[this.selectedRangeDates.length - 1].getTime()
@@ -794,9 +796,11 @@ class WebsyDatePicker {
794
796
  else if (this.options.mode === 'hour') {
795
797
  dateEl = document.getElementById(`${this.elementId}_${d}_hour`)
796
798
  }
797
- dateEl.classList.add('selected')
798
- dateEl.classList.add('first')
799
- dateEl.classList.add('last')
799
+ if (dateEl) {
800
+ dateEl.classList.add('selected')
801
+ dateEl.classList.add('first')
802
+ dateEl.classList.add('last')
803
+ }
800
804
  })
801
805
  }
802
806
  }
@@ -1005,7 +1009,7 @@ class WebsyDatePicker {
1005
1009
  }
1006
1010
  html += paddedDays.join('')
1007
1011
  }
1008
- 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('')
1012
+ 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('')
1009
1013
  html += `
1010
1014
  </ul>
1011
1015
  </div>
@@ -1018,7 +1022,7 @@ class WebsyDatePicker {
1018
1022
  yearList.reverse()
1019
1023
  }
1020
1024
  html += `<div id='${this.elementId}_dateList' class='websy-dp-date-list'><ul>`
1021
- html += yearList.map(d => `<li id='${this.elementId}_${d.id}_year' class='websy-dp-date websy-dp-year ${d.disabled === true ? 'websy-disabled-date' : ''}'>${d.year}</li>`).join('')
1025
+ html += yearList.map(d => `<li id='${this.elementId}_${d.id}_year' data-id='${d.id}' class='websy-dp-date websy-dp-year ${d.disabled === true ? 'websy-disabled-date' : ''}'>${d.year}</li>`).join('')
1022
1026
  html += `</ul></div>`
1023
1027
  }
1024
1028
  else if (this.options.mode === 'monthyear') {
@@ -1035,7 +1039,7 @@ class WebsyDatePicker {
1035
1039
  }
1036
1040
  html += paddedMonths.join('')
1037
1041
  }
1038
- html += this.monthYears[year].map(d => `<li id='${this.elementId}_${d.id}_monthyear' data-year='${d.year}' class='websy-dp-date websy-dp-monthyear'>${d.month}</li>`).join('')
1042
+ html += this.monthYears[year].map(d => `<li id='${this.elementId}_${d.id}_monthyear' data-id='${d.id}' data-year='${d.year}' class='websy-dp-date websy-dp-monthyear'>${d.month}</li>`).join('')
1039
1043
  html += `</ul>`
1040
1044
  }
1041
1045
  html += `</div>`
@@ -1126,17 +1130,8 @@ class WebsyDatePicker {
1126
1130
  selectRange (index, confirm = true) {
1127
1131
  if (this.options.ranges[this.options.mode][index]) {
1128
1132
  this.selectedRangeDates = [...this.options.ranges[this.options.mode][index].range]
1129
- this.currentselection = [...this.options.ranges[this.options.mode][index].range]
1133
+ this.currentselection = this.options.ranges[this.options.mode][index].range.map(d => d.getTime())
1130
1134
  this.selectedRange = +index
1131
- const el = document.getElementById(`${this.elementId}_header`)
1132
- if (el) {
1133
- if (this.selectedRange === 0) {
1134
- el.classList.remove('range-selected')
1135
- }
1136
- else {
1137
- el.classList.add('range-selected')
1138
- }
1139
- }
1140
1135
  this.highlightRange()
1141
1136
  this.updateRange()
1142
1137
  this.close(confirm, true)
@@ -1145,14 +1140,16 @@ class WebsyDatePicker {
1145
1140
  selectCustomRange (rangeInput) {
1146
1141
  this.selectedRange = -1
1147
1142
  let isContinuousRange = true
1148
- if (rangeInput.length === 1) {
1149
- this.selectedRangeDates = [...rangeInput]
1150
- this.customRangeSelected = true
1151
- }
1152
- else if (rangeInput.length === 2) {
1153
- this.selectedRangeDates = [...rangeInput]
1154
- this.customRangeSelected = true
1155
- }
1143
+ // if (rangeInput.length === 1) {
1144
+ // this.selectedRangeDates = [...rangeInput]
1145
+ // this.customRangeSelected = true
1146
+ // }
1147
+ // else if (rangeInput.length === 2) {
1148
+ // this.selectedRangeDates = [...rangeInput]
1149
+ // this.customRangeSelected = true
1150
+ // }
1151
+ this.selectedRangeDates = [...rangeInput]
1152
+ this.customRangeSelected = true
1156
1153
  rangeInput.forEach((r, i) => {
1157
1154
  if (i > 0) {
1158
1155
  if (this.options.mode === 'date' || this.options.mode === 'monthyear') {
@@ -1290,6 +1287,15 @@ class WebsyDatePicker {
1290
1287
  if (labelEl) {
1291
1288
  labelEl.innerHTML = range.label
1292
1289
  }
1290
+ const headerEl = document.getElementById(`${this.elementId}_header`)
1291
+ if (headerEl) {
1292
+ if (this.selectedRange === 0) {
1293
+ headerEl.classList.remove('range-selected')
1294
+ }
1295
+ else {
1296
+ headerEl.classList.add('range-selected')
1297
+ }
1298
+ }
1293
1299
  }
1294
1300
  }
1295
1301
 
@@ -1411,6 +1417,7 @@ class WebsyDropdown {
1411
1417
  if (typeof d.index === 'undefined') {
1412
1418
  d.index = i
1413
1419
  }
1420
+ d.currentIndex = i
1414
1421
  return d
1415
1422
  })
1416
1423
  const headerEl = document.getElementById(`${this.elementId}_header`)
@@ -1418,15 +1425,17 @@ class WebsyDropdown {
1418
1425
  headerEl.classList[`${this.options.allowClear === true ? 'add' : 'remove'}`]('allow-clear')
1419
1426
  }
1420
1427
  const el = document.getElementById(`${this.elementId}_items`)
1421
- if (el.childElementCount === 0) {
1422
- this.render()
1423
- }
1424
- else {
1425
- if (this.options.items.length === 0) {
1426
- this.options.items = [{label: this.options.noItemsText || 'No Items'}]
1428
+ if (el) {
1429
+ if (el.childElementCount === 0) {
1430
+ this.render()
1427
1431
  }
1428
- this.renderItems()
1429
- }
1432
+ else {
1433
+ if (this.options.items.length === 0) {
1434
+ this.options.items = [{label: this.options.noItemsText || 'No Items'}]
1435
+ }
1436
+ this.renderItems()
1437
+ }
1438
+ }
1430
1439
  }
1431
1440
  get data () {
1432
1441
  return this.options.items
@@ -1667,6 +1676,10 @@ class WebsyDropdown {
1667
1676
  const labelEl = document.getElementById(`${this.elementId}_selectedItems`)
1668
1677
  const inputEl = document.getElementById(`${this.elementId}_input`)
1669
1678
  const itemEls = el.querySelectorAll(`.websy-dropdown-item`)
1679
+ let dataToUse = this._originalData
1680
+ if (this.options.onSearch) {
1681
+ dataToUse = this.options.items
1682
+ }
1670
1683
  for (let i = 0; i < itemEls.length; i++) {
1671
1684
  itemEls[i].classList.remove('active')
1672
1685
  let index = itemEls[i].getAttribute('data-index')
@@ -1702,14 +1715,14 @@ class WebsyDropdown {
1702
1715
  }
1703
1716
  else if (this.selectedItems.length > 1) {
1704
1717
  if (this.options.showCompleteSelectedList === true) {
1705
- let selectedLabels = this.selectedItems.map(s => this.options.items[s].label || this.options.items[s].value).join(this.options.multiValueDelimiter)
1706
- let selectedValues = this.selectedItems.map(s => this.options.items[s].value || this.options.items[s].label).join(this.options.multiValueDelimiter)
1718
+ let selectedLabels = this.selectedItems.map(s => dataToUse[s].label || dataToUse[s].value).join(this.options.multiValueDelimiter)
1719
+ let selectedValues = this.selectedItems.map(s => dataToUse[s].value || dataToUse[s].label).join(this.options.multiValueDelimiter)
1707
1720
  labelEl.innerHTML = selectedLabels
1708
1721
  labelEl.setAttribute('data-info', selectedLabels)
1709
1722
  inputEl.value = selectedValues
1710
1723
  }
1711
1724
  else {
1712
- let selectedValues = this.selectedItems.map(s => this.options.items[s].value || this.options.items[s].label).join(this.options.multiValueDelimiter)
1725
+ let selectedValues = this.selectedItems.map(s => dataToUse[s].value || dataToUse[s].label).join(this.options.multiValueDelimiter)
1713
1726
  labelEl.innerHTML = `${this.selectedItems.length} selected`
1714
1727
  labelEl.setAttribute('data-info', '')
1715
1728
  inputEl.value = selectedValues
@@ -1723,6 +1736,10 @@ class WebsyDropdown {
1723
1736
  }
1724
1737
  }
1725
1738
  updateSelected (index) {
1739
+ let dataToUse = this._originalData && this._originalData.length > 0 ? this._originalData : this.options.items
1740
+ if (this.options.onSearch) {
1741
+ dataToUse = this.options.items
1742
+ }
1726
1743
  if (typeof index !== 'undefined' && index !== null) {
1727
1744
  let pos = this.selectedItems.indexOf(index)
1728
1745
  if (this.options.multiSelect === false) {
@@ -1738,10 +1755,10 @@ class WebsyDropdown {
1738
1755
  }
1739
1756
  }
1740
1757
  // const item = this.options.items[index]
1741
- const item = this._originalData[index] || this.options.items[index]
1758
+ const item = dataToUse[index]
1742
1759
  this.updateHeader(item)
1743
1760
  if (item && this.options.onItemSelected) {
1744
- this.options.onItemSelected(item, this.selectedItems, this._originalData || this.options.items, this.options)
1761
+ this.options.onItemSelected(item, this.selectedItems, dataToUse, this.options)
1745
1762
  }
1746
1763
  if (this.options.closeAfterSelection === true) {
1747
1764
  this.close()
@@ -1755,7 +1772,8 @@ class WebsyDragDrop {
1755
1772
  const DEFAULTS = {
1756
1773
  items: [],
1757
1774
  orientation: 'horizontal',
1758
- dropPlaceholder: 'Drop item here'
1775
+ dropPlaceholder: 'Drop item here',
1776
+ accepts: 'application/wd-item'
1759
1777
  }
1760
1778
  this.busy = false
1761
1779
  this.options = Object.assign({}, DEFAULTS, options)
@@ -1781,9 +1799,7 @@ class WebsyDragDrop {
1781
1799
  else {
1782
1800
  console.error(`No element found with ID ${this.elementId}`)
1783
1801
  }
1784
- GlobalPubSub.subscribe(this.elementId, 'requestForDDItem', this.handleRequestForItem.bind(this))
1785
- console.log('constructor dd')
1786
- console.trace()
1802
+ GlobalPubSub.subscribe(this.elementId, 'requestForDDItem', this.handleRequestForItem.bind(this))
1787
1803
  GlobalPubSub.subscribe(this.elementId, 'add', this.addItem.bind(this))
1788
1804
  this.render()
1789
1805
  }
@@ -1816,7 +1832,7 @@ class WebsyDragDrop {
1816
1832
  item.id = WebsyDesigns.Utils.createIdentity()
1817
1833
  }
1818
1834
  let html = `
1819
- <div id='${item.id}_item' class='websy-dragdrop-item' draggable='true' data-id='${item.id}'>
1835
+ <div id='${item.id}_item' class='websy-dragdrop-item ${(item.classes || []).join(' ')}' draggable='true' data-id='${item.id}'>
1820
1836
  <div id='${item.id}_itemInner' class='websy-dragdrop-item-inner' data-id='${item.id}'>
1821
1837
  `
1822
1838
  if (item.component) {
@@ -1845,24 +1861,27 @@ class WebsyDragDrop {
1845
1861
  }
1846
1862
  handleDragStart (event) {
1847
1863
  this.draggedId = event.target.getAttribute('data-id')
1848
- event.dataTransfer.effectAllowed = 'move'
1849
- event.dataTransfer.setData('application/wd-item', JSON.stringify({el: event.target.id, id: this.elementId, itemId: this.draggedId}))
1850
- console.log('drag start', event)
1851
- event.target.style.opacity = 0.5
1864
+ event.dataTransfer.effectAllowed = 'move'
1865
+ event.dataTransfer.setData(this.options.accepts, JSON.stringify({el: event.target.id, id: this.elementId, itemId: this.draggedId}))
1866
+ event.target.classList.add('dragging')
1867
+ // event.target.style.opacity = 0.5
1852
1868
  this.dragging = true
1853
1869
  }
1854
- handleDragOver (event) {
1855
- console.log('drag over', event.target.classList)
1870
+ handleDragOver (event) {
1856
1871
  if (event.preventDefault) {
1857
1872
  event.preventDefault()
1858
1873
  }
1874
+ console.log('drag', event.target.classList)
1859
1875
  if (!event.target.classList.contains('droppable')) {
1860
1876
  return
1861
1877
  }
1878
+ if (event.dataTransfer.types.indexOf(this.options.accepts) === -1) {
1879
+ return
1880
+ }
1862
1881
  event.target.classList.add('drag-over')
1863
1882
  }
1864
1883
  handleDragLeave (event) {
1865
- console.log('drag leave', event.target.classList)
1884
+ // console.log('drag leave', event.target.classList)
1866
1885
  if (!event.target.classList.contains('droppable')) {
1867
1886
  return
1868
1887
  }
@@ -1873,15 +1892,18 @@ class WebsyDragDrop {
1873
1892
  // this.removeExpandedDrop(side, id, droppedItem)
1874
1893
  }
1875
1894
  handleDrop (event) {
1876
- console.log('drag drop')
1877
- console.log(event.dataTransfer.getData('application/wd-item'))
1878
- const data = JSON.parse(event.dataTransfer.getData('application/wd-item'))
1895
+ // console.log('drag drop')
1896
+ // console.log(event.dataTransfer.getData('application/wd-item'))
1897
+ const data = JSON.parse(event.dataTransfer.getData(this.options.accepts))
1879
1898
  if (event.preventDefault) {
1880
1899
  event.preventDefault()
1881
1900
  }
1882
1901
  if (!event.target.classList.contains('droppable')) {
1883
1902
  return
1884
1903
  }
1904
+ if (event.dataTransfer.types.indexOf(this.options.accepts) === -1) {
1905
+ return
1906
+ }
1885
1907
  let side = event.target.getAttribute('data-side')
1886
1908
  let id = event.target.getAttribute('data-id')
1887
1909
  let index = this.getItemIndex(id)
@@ -1891,7 +1913,7 @@ class WebsyDragDrop {
1891
1913
  index += 1
1892
1914
  }
1893
1915
  if (draggedIndex === -1) {
1894
- console.log('requestForDDItem')
1916
+ // console.log('requestForDDItem')
1895
1917
  GlobalPubSub.publish(data.id, 'requestForDDItem', {
1896
1918
  group: this.options.group,
1897
1919
  source: data.id,
@@ -1929,8 +1951,9 @@ class WebsyDragDrop {
1929
1951
  }
1930
1952
  }
1931
1953
  handleDragEnd (event) {
1932
- console.log('drag end')
1954
+ // console.log('drag end')
1933
1955
  event.target.style.opacity = 1
1956
+ event.target.classList.remove('dragging')
1934
1957
  this.draggedId = null
1935
1958
  this.dragging = false
1936
1959
  const startEl = document.getElementById(`${this.elementId}start_item`)
@@ -3002,9 +3025,9 @@ class WebsyPubSub {
3002
3025
  }
3003
3026
  }
3004
3027
  else {
3005
- if (this.subscriptions[method]) {
3006
- this.subscriptions[method].forEach(fn => {
3007
- fn(data)
3028
+ if (this.subscriptions[id]) {
3029
+ this.subscriptions[id].forEach(fn => {
3030
+ fn(method)
3008
3031
  })
3009
3032
  }
3010
3033
  }
@@ -3019,10 +3042,10 @@ class WebsyPubSub {
3019
3042
  }
3020
3043
  }
3021
3044
  else {
3022
- if (!this.subscriptions[method]) {
3023
- this.subscriptions[method] = []
3045
+ if (!this.subscriptions[id]) {
3046
+ this.subscriptions[id] = []
3024
3047
  }
3025
- this.subscriptions[method].push(fn)
3048
+ this.subscriptions[id].push(method)
3026
3049
  }
3027
3050
  }
3028
3051
  }
@@ -4020,6 +4043,55 @@ class WebsyRouter {
4020
4043
  }
4021
4044
  }
4022
4045
 
4046
+ class WebsySearch {
4047
+ constructor (elementId, options) {
4048
+ this.elementId = elementId
4049
+ const DEFAULTS = {
4050
+ 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>`,
4051
+ 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>`,
4052
+ placeholder: 'Search',
4053
+ searchTimeout: 500,
4054
+ minLength: 2
4055
+ }
4056
+ this.options = Object.assign({}, DEFAULTS, options)
4057
+ this.searchTimeoutFn = null
4058
+ const el = document.getElementById(elementId)
4059
+ if (el) {
4060
+ // el.addEventListener('click', this.handleClick.bind(this))
4061
+ el.addEventListener('keyup', this.handleKeyUp.bind(this))
4062
+ el.innerHTML = `
4063
+ <div class='websy-search-input-container'>
4064
+ ${this.options.searchIcon}
4065
+ <input id='${this.elementId}_search' class='websy-search-input' placeholder='${this.options.placeholder || 'Search'}'>
4066
+ ${this.options.clearIcon}
4067
+ </div>
4068
+ `
4069
+ }
4070
+ else {
4071
+ console.log('No element found with Id', elementId)
4072
+ }
4073
+ }
4074
+ handleKeyUp (event) {
4075
+ if (event.target.classList.contains('websy-search-input')) {
4076
+ if (this.searchTimeoutFn) {
4077
+ clearTimeout(this.searchTimeoutFn)
4078
+ }
4079
+ if (event.target.value.length >= this.options.minLength) {
4080
+ this.searchTimeoutFn = setTimeout(() => {
4081
+ if (this.options.onSearch) {
4082
+ this.options.onSearch(event.target.value)
4083
+ }
4084
+ }, this.options.searchTimeout)
4085
+ }
4086
+ else {
4087
+ if (this.options.onSearch) {
4088
+ this.options.onSearch('')
4089
+ }
4090
+ }
4091
+ }
4092
+ }
4093
+ }
4094
+
4023
4095
  /* global WebsyDesigns ENVIRONMENT */
4024
4096
  class WebsySignup {
4025
4097
  constructor (elementId, options) {
@@ -4295,6 +4367,7 @@ const WebsyUtils = {
4295
4367
  let red = 0
4296
4368
  let green = 0
4297
4369
  let blue = 0
4370
+ let alpha = 1
4298
4371
  if (backgroundColor.indexOf('#') !== -1) {
4299
4372
  // hex color
4300
4373
  backgroundColor = backgroundColor.replace('#', '')
@@ -4306,13 +4379,15 @@ const WebsyUtils = {
4306
4379
  }
4307
4380
  else if (backgroundColor.toLowerCase().indexOf('rgb') !== -1) {
4308
4381
  // rgb color
4309
- colorParts = backgroundColor.replace(/rgb\(/gi, '').replace(/\)/gi, '')
4382
+ colorParts = backgroundColor.replace(/rgba\(/gi, '').replace(/\)/gi, '')
4383
+ colorParts = colorParts.replace(/rgb\(/gi, '')
4310
4384
  colorParts = colorParts.split(',')
4311
4385
  red = colorParts[0]
4312
4386
  green = colorParts[1]
4313
4387
  blue = colorParts[2]
4388
+ alpha = colorParts[3] || 1
4314
4389
  }
4315
- return (red * 0.299 + green * 0.587 + blue * 0.114) > 186 ? darkColor : lightColor
4390
+ return ((red * 0.299 + green * 0.587 + blue * 0.114) / alpha) > 186 ? darkColor : lightColor
4316
4391
  },
4317
4392
  measureText (text, rotation = 0, fontSize = '12px') {
4318
4393
  if (!isNaN(fontSize)) {
@@ -4762,8 +4837,15 @@ class WebsyTable {
4762
4837
  }
4763
4838
  let headHTML = '<tr>' + this.options.columns.map((c, i) => {
4764
4839
  if (c.show !== false) {
4840
+ let style = ''
4841
+ if (c.style) {
4842
+ style += c.style
4843
+ }
4844
+ if (c.width) {
4845
+ style += `width: ${(c.width || 'auto')};`
4846
+ }
4765
4847
  return `
4766
- <th ${c.width ? 'style="width: ' + (c.width || 'auto') + ';"' : ''}>
4848
+ <th style="${style}">
4767
4849
  <div class ="tableHeader">
4768
4850
  <div class="leftSection">
4769
4851
  <div
@@ -5438,7 +5520,8 @@ class WebsyTable3 {
5438
5520
  showTotalsAbove: true,
5439
5521
  minHandleSize: 20,
5440
5522
  maxColWidth: '50%',
5441
- allowPivoting: false
5523
+ allowPivoting: false,
5524
+ 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>`
5442
5525
  }
5443
5526
  this.options = Object.assign({}, DEFAULTS, options)
5444
5527
  this.sizes = {}
@@ -5549,9 +5632,29 @@ class WebsyTable3 {
5549
5632
  data.forEach(row => {
5550
5633
  bodyHtml += `<tr class="websy-table-row">`
5551
5634
  row.forEach((cell, cellIndex) => {
5635
+ if (typeof sizingColumns[cellIndex] === 'undefined') {
5636
+ return // need to revisit this logic
5637
+ }
5638
+ let style = ''
5639
+ if (cell.style) {
5640
+ style += cell.style
5641
+ }
5642
+ if (useWidths === true) {
5643
+ style += `max-width: ${sizingColumns[cellIndex].width || sizingColumns[cellIndex].actualWidth}px!important;`
5644
+ }
5645
+ if (cell.backgroundColor) {
5646
+ style += `background-color: ${cell.backgroundColor}; `
5647
+ if (!cell.color) {
5648
+ style += `color: ${WebsyDesigns.Utils.getLightDark(cell.backgroundColor)}; `
5649
+ }
5650
+ }
5651
+ if (cell.color) {
5652
+ style += `color: ${cell.color}; `
5653
+ }
5654
+ console.log('rowspan', cell.rowspan)
5552
5655
  bodyHtml += `<td
5553
- class='websy-table-cell'
5554
- style='${cell.style}'
5656
+ class='websy-table-cell ${(cell.classes || []).join(' ')}'
5657
+ style='${style}'
5555
5658
  data-info='${cell.value}'
5556
5659
  colspan='${cell.colspan || 1}'
5557
5660
  rowspan='${cell.rowspan || 1}'
@@ -5590,7 +5693,7 @@ class WebsyTable3 {
5590
5693
  return
5591
5694
  }
5592
5695
  headerHtml += `<tr class="websy-table-row websy-table-header-row">`
5593
- row.forEach(col => {
5696
+ row.forEach((col, colIndex) => {
5594
5697
  headerHtml += `<td
5595
5698
  class='websy-table-cell'
5596
5699
  style='${col.style}'
@@ -5605,13 +5708,35 @@ class WebsyTable3 {
5605
5708
  // }
5606
5709
  headerHtml += `
5607
5710
  >
5608
- ${col.name}
5711
+ <div>
5712
+ ${col.name}
5713
+ ${col.searchable === true ? this.buildSearchIcon(col, colIndex) : ''}
5714
+ </div>
5609
5715
  </td>`
5610
5716
  })
5611
5717
  headerHtml += `</tr>`
5612
5718
  })
5719
+ const dropdownEl = document.getElementById(`${this.elementId}_dropdownContainer`)
5720
+ this.options.columns[this.options.columns.length - 1].forEach((c, i) => {
5721
+ if (c.searchable && c.isExternalSearch === true) {
5722
+ const testEl = document.getElementById(`${this.elementId}_columnSearch_${c.dimId || i}`)
5723
+ if (!testEl) {
5724
+ const newE = document.createElement('div')
5725
+ newE.id = `${this.elementId}_columnSearch_${c.dimId || i}`
5726
+ newE.className = 'websy-modal-dropdown'
5727
+ dropdownEl.appendChild(newE)
5728
+ }
5729
+ }
5730
+ })
5613
5731
  return headerHtml
5614
5732
  }
5733
+ buildSearchIcon (col, index) {
5734
+ return `
5735
+ <div class="websy-table-search-icon" data-col-id="${col.dimId}" data-col-index="${index}">
5736
+ <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>
5737
+ </div>
5738
+ `
5739
+ }
5615
5740
  buildTotalHtml (useWidths = false) {
5616
5741
  if (!this.options.totals) {
5617
5742
  return ''
@@ -5687,11 +5812,13 @@ class WebsyTable3 {
5687
5812
  }
5688
5813
  })
5689
5814
  this.sizes.totalWidth = this.options.columns[this.options.columns.length - 1].reduce((a, b) => a + (b.width || b.actualWidth), 0)
5815
+ this.sizes.totalNonPinnedWidth = this.options.columns[this.options.columns.length - 1].filter((c, i) => i >= this.pinnedColumns).reduce((a, b) => a + (b.width || b.actualWidth), 0)
5690
5816
  const outerSize = outerEl.getBoundingClientRect()
5691
5817
  if (this.sizes.totalWidth < outerSize.width) {
5692
5818
  this.sizes.totalWidth = 0
5819
+ this.sizes.totalNonPinnedWidth = 0
5693
5820
  let equalWidth = outerSize.width / this.options.columns[this.options.columns.length - 1].length
5694
- this.options.columns[this.options.columns.length - 1].forEach((c, i) => {
5821
+ this.options.columns[this.options.columns.length - 1].forEach((c, i) => {
5695
5822
  if (!c.width) {
5696
5823
  if (c.actualWidth < equalWidth) {
5697
5824
  // adjust the width
@@ -5699,6 +5826,9 @@ class WebsyTable3 {
5699
5826
  }
5700
5827
  }
5701
5828
  this.sizes.totalWidth += c.width || c.actualWidth
5829
+ if (i < this.pinnedColumns) {
5830
+ this.sizes.totalNonPinnedWidth += c.width || c.actualWidth
5831
+ }
5702
5832
  equalWidth = (outerSize.width - this.sizes.totalWidth) / (this.options.columns[this.options.columns.length - 1].length - (i + 1))
5703
5833
  })
5704
5834
  }
@@ -5719,9 +5849,15 @@ class WebsyTable3 {
5719
5849
  if (this.sizes.rowsToRender < this.totalRowCount) {
5720
5850
  this.vScrollRequired = true
5721
5851
  }
5852
+ else {
5853
+ this.vScrollRequired = false
5854
+ }
5722
5855
  if (this.sizes.totalWidth > this.sizes.outer.width) {
5723
5856
  this.hScrollRequired = true
5724
5857
  }
5858
+ else {
5859
+ this.hScrollRequired = false
5860
+ }
5725
5861
  this.options.allColumns = this.options.columns.map(c => c)
5726
5862
  console.log('sizes', this.sizes)
5727
5863
  return this.sizes
@@ -5748,7 +5884,13 @@ class WebsyTable3 {
5748
5884
  return output
5749
5885
  }
5750
5886
  handleClick (event) {
5751
-
5887
+ if (event.target.classList.contains('websy-table-search-icon')) {
5888
+ console.log('clicked on search icon')
5889
+ const colIndex = +event.target.getAttribute('data-col-index')
5890
+ if (this.options.columns[this.options.columns.length - 1][colIndex].onSearch) {
5891
+ this.options.columns[this.options.columns.length - 1][colIndex].onSearch(event, this.options.columns[this.options.columns.length - 1][colIndex])
5892
+ }
5893
+ }
5752
5894
  }
5753
5895
  handleMouseDown (event) {
5754
5896
  if (event.target.classList.contains('websy-scroll-handle-y')) {
@@ -5845,20 +5987,26 @@ class WebsyTable3 {
5845
5987
  bodyEl.style.height = `calc(100% - ${this.sizes.header.height}px - ${this.sizes.total.height}px)`
5846
5988
  if (this.options.virtualScroll === true) {
5847
5989
  // set the scroll element positions
5848
- if (this.vScrollRequired === true) {
5849
- let vScrollEl = document.getElementById(`${this.elementId}_vScrollContainer`)
5850
- let vHandleEl = document.getElementById(`${this.elementId}_vScrollHandle`)
5990
+ let vScrollEl = document.getElementById(`${this.elementId}_vScrollContainer`)
5991
+ let vHandleEl = document.getElementById(`${this.elementId}_vScrollHandle`)
5992
+ if (this.vScrollRequired === true) {
5851
5993
  vScrollEl.style.top = `${this.sizes.header.height + this.sizes.total.height}px`
5852
5994
  vScrollEl.style.height = `${this.sizes.bodyHeight}px`
5853
5995
  vHandleEl.style.height = Math.max(this.options.minHandleSize, this.sizes.bodyHeight * (this.sizes.rowsToRenderPrecise / this.totalRowCount)) + 'px'
5854
- }
5855
- if (this.hScrollRequired === true) {
5856
- let hScrollEl = document.getElementById(`${this.elementId}_hScrollContainer`)
5857
- let hHandleEl = document.getElementById(`${this.elementId}_hScrollHandle`)
5996
+ }
5997
+ else {
5998
+ vHandleEl.style.height = '0px'
5999
+ }
6000
+ let hScrollEl = document.getElementById(`${this.elementId}_hScrollContainer`)
6001
+ let hHandleEl = document.getElementById(`${this.elementId}_hScrollHandle`)
6002
+ if (this.hScrollRequired === true) {
5858
6003
  hScrollEl.style.left = `${this.sizes.table.width - this.sizes.scrollableWidth}px`
5859
6004
  hScrollEl.style.width = `${this.sizes.scrollableWidth - 20}px`
5860
- hHandleEl.style.width = Math.max(this.options.minHandleSize, this.sizes.scrollableWidth * (this.sizes.scrollableWidth / this.sizes.totalWidth)) + 'px'
5861
- }
6005
+ hHandleEl.style.width = Math.max(this.options.minHandleSize, this.sizes.scrollableWidth * (this.sizes.scrollableWidth / this.sizes.totalNonPinnedWidth)) + 'px'
6006
+ }
6007
+ else {
6008
+ hHandleEl.style.width = '0px'
6009
+ }
5862
6010
  }
5863
6011
  }
5864
6012
  renderColumnHeaders () {
@@ -5887,9 +6035,7 @@ class WebsyTable3 {
5887
6035
  const el = document.getElementById(`${this.elementId}_tableContainer`)
5888
6036
  if (el) {
5889
6037
  el.classList.add('has-error')
5890
- }
5891
- const tableEl = document.getElementById(`${this.elementId}_tableInner`)
5892
- tableEl.classList.add('hidden')
6038
+ }
5893
6039
  const containerEl = document.getElementById(`${this.elementId}_errorContainer`)
5894
6040
  if (containerEl) {
5895
6041
  containerEl.classList.add('active')
@@ -5908,6 +6054,19 @@ class WebsyTable3 {
5908
6054
  }
5909
6055
  }
5910
6056
  scrollX (diff) {
6057
+ const el = document.getElementById(`${this.elementId}_tableContainer`)
6058
+ if (!el.classList.contains('scrolling')) {
6059
+ el.classList.add('scrolling')
6060
+ }
6061
+ if (this.scrollTimeoutFn) {
6062
+ clearTimeout(this.scrollTimeoutFn)
6063
+ }
6064
+ this.scrollTimeoutFn = setTimeout(() => {
6065
+ el.classList.remove('scrolling')
6066
+ }, 200)
6067
+ if (this.hScrollRequired === false) {
6068
+ return
6069
+ }
5911
6070
  const scrollContainerEl = document.getElementById(`${this.elementId}_hScrollContainer`)
5912
6071
  const scrollHandleEl = document.getElementById(`${this.elementId}_hScrollHandle`)
5913
6072
  let handlePos
@@ -5921,13 +6080,13 @@ class WebsyTable3 {
5921
6080
  console.log('dragging x', diff, scrollContainerEl.getBoundingClientRect().width - scrollHandleEl.getBoundingClientRect().width)
5922
6081
  scrollHandleEl.style.left = Math.min(scrollableSpace, Math.max(0, handlePos)) + 'px'
5923
6082
  if (this.options.onScroll) {
5924
- let actualLeft = (this.sizes.totalWidth - this.sizes.scrollableWidth) * (Math.min(scrollableSpace, Math.max(0, handlePos)) / scrollableSpace)
6083
+ let actualLeft = (this.sizes.totalNonPinnedWidth - this.sizes.scrollableWidth) * (Math.min(scrollableSpace, Math.max(0, handlePos)) / scrollableSpace)
5925
6084
  let cumulativeWidth = 0
5926
6085
  this.startCol = 0
5927
6086
  this.endCol = 0
5928
- for (let i = 0; i < this.options.allColumns[this.options.allColumns.length - 1].length; i++) {
6087
+ for (let i = this.pinnedColumns; i < this.options.allColumns[this.options.allColumns.length - 1].length; i++) {
5929
6088
  cumulativeWidth += this.options.allColumns[this.options.allColumns.length - 1][i].actualWidth
5930
- console.log(actualLeft, this.sizes.totalWidth, cumulativeWidth, cumulativeWidth + this.options.allColumns[this.options.allColumns.length - 1][i].actualWidth)
6089
+ console.log('actualLeft', actualLeft, this.sizes.totalWidth, cumulativeWidth, cumulativeWidth + this.options.allColumns[this.options.allColumns.length - 1][i].actualWidth)
5931
6090
  if (actualLeft < cumulativeWidth) {
5932
6091
  this.startCol = i
5933
6092
  break
@@ -5951,6 +6110,19 @@ class WebsyTable3 {
5951
6110
  }
5952
6111
  }
5953
6112
  scrollY (diff) {
6113
+ const el = document.getElementById(`${this.elementId}_tableContainer`)
6114
+ if (!el.classList.contains('scrolling')) {
6115
+ el.classList.add('scrolling')
6116
+ }
6117
+ if (this.scrollTimeoutFn) {
6118
+ clearTimeout(this.scrollTimeoutFn)
6119
+ }
6120
+ this.scrollTimeoutFn = setTimeout(() => {
6121
+ el.classList.remove('scrolling')
6122
+ }, 200)
6123
+ if (this.vScrollRequired === false) {
6124
+ return
6125
+ }
5954
6126
  const scrollContainerEl = document.getElementById(`${this.elementId}_vScrollContainer`)
5955
6127
  const scrollHandleEl = document.getElementById(`${this.elementId}_vScrollHandle`)
5956
6128
  let handlePos
@@ -6902,7 +7074,7 @@ bars
6902
7074
  .attr('x', getBarX.bind(this))
6903
7075
  .attr('y', getBarY.bind(this))
6904
7076
  .transition(this.transition)
6905
- .attr('fill', d => d.color || series.color)
7077
+ .attr('fill', d => d.y.color || d.color || series.color)
6906
7078
 
6907
7079
  bars
6908
7080
  .enter()
@@ -6912,7 +7084,7 @@ bars
6912
7084
  .attr('x', getBarX.bind(this))
6913
7085
  .attr('y', getBarY.bind(this))
6914
7086
  // .transition(this.transition)
6915
- .attr('fill', d => d.color || series.color)
7087
+ .attr('fill', d => d.y.color || d.color || series.color)
6916
7088
  .attr('class', d => {
6917
7089
  return `bar bar_${series.key}`
6918
7090
  })
@@ -6927,7 +7099,7 @@ if (this.options.orientation === 'horizontal') {
6927
7099
  xAxis = 'leftAxis'
6928
7100
  yAxis = 'bottomAxis'
6929
7101
  }
6930
- if (this.options.showLabels) {
7102
+ if (this.options.showLabels === true || series.showLabels === true) {
6931
7103
  // need to add logic to handle positioning options
6932
7104
  // e.g. Inside, Outide, Auto (this will also affect the available plot space)
6933
7105
  // We currently only support 'Auto'
@@ -6941,10 +7113,30 @@ if (this.options.showLabels) {
6941
7113
  .attr('x', getLabelX.bind(this))
6942
7114
  .attr('y', getLabelY.bind(this))
6943
7115
  .attr('class', `label_${series.key}`)
6944
- .style('font-size', `${this.options.labelSize || this.options.fontSize}px`)
6945
- .style('fill', d => this.options.labelColor || WebsyDesigns.WebsyUtils.getLightDark(d.color || series.color))
7116
+ .attr('fill', d => this.options.labelColor || WebsyDesigns.WebsyUtils.getLightDark(d.y.color || d.color || series.color))
7117
+ .style('font-size', `${this.options.labelSize || this.options.fontSize}px`)
6946
7118
  .transition(this.transition)
6947
7119
  .text(d => d.y.label || d.y.value)
7120
+ .each(function (d, i) {
7121
+ if (that.options.orientation === 'horizontal') {
7122
+ if (that.options.grouping === 'stacked') {
7123
+ this.setAttribute('text-anchor', 'middle')
7124
+ }
7125
+ else if (that.plotWidth - getLabelX.call(that, d) < this.getComputedTextLength()) {
7126
+ this.setAttribute('text-anchor', 'end')
7127
+ this.setAttribute('x', +(this.getAttribute('x')) - 8)
7128
+ this.setAttribute('fill', that.options.labelColor || WebsyDesigns.WebsyUtils.getLightDark(d.y.color || d.color || series.color))
7129
+ }
7130
+ else {
7131
+ this.setAttribute('fill', that.options.labelColor || WebsyDesigns.WebsyUtils.getLightDark('#ffffff'))
7132
+ }
7133
+ }
7134
+ else {
7135
+ if (that.plotheight - getLabelX.call(that, d) < (that.options.labelSize || that.options.fontSize)) {
7136
+ this.setAttribute('y', +(this.getAttribute('y')) + 8)
7137
+ }
7138
+ }
7139
+ })
6948
7140
 
6949
7141
  labels
6950
7142
  .enter()
@@ -6954,8 +7146,8 @@ if (this.options.showLabels) {
6954
7146
  .attr('y', getLabelY.bind(this))
6955
7147
  .attr('alignment-baseline', 'central')
6956
7148
  .attr('text-anchor', this.options.orientation === 'horizontal' ? 'left' : 'middle')
6957
- .style('font-size', `${this.options.labelSize || this.options.fontSize}px`)
6958
- .style('fill', d => this.options.labelColor || WebsyDesigns.WebsyUtils.getLightDark(d.color || series.color))
7149
+ .attr('fill', d => this.options.labelColor || WebsyDesigns.WebsyUtils.getLightDark(d.y.color || d.color || series.color))
7150
+ .style('font-size', `${this.options.labelSize || this.options.fontSize}px`)
6959
7151
  .text(d => d.y.label || d.y.value)
6960
7152
  .each(function (d, i) {
6961
7153
  if (that.options.orientation === 'horizontal') {
@@ -6964,8 +7156,12 @@ if (this.options.showLabels) {
6964
7156
  }
6965
7157
  else if (that.plotWidth - getLabelX.call(that, d) < this.getComputedTextLength()) {
6966
7158
  this.setAttribute('text-anchor', 'end')
6967
- this.setAttribute('x', +(this.getAttribute('x')) - 8)
7159
+ this.setAttribute('x', +(this.getAttribute('x')) - 8)
7160
+ this.setAttribute('fill', that.options.labelColor || WebsyDesigns.WebsyUtils.getLightDark(d.y.color || d.color || series.color))
6968
7161
  }
7162
+ else {
7163
+ this.setAttribute('fill', that.options.labelColor || WebsyDesigns.WebsyUtils.getLightDark('#ffffff'))
7164
+ }
6969
7165
  }
6970
7166
  else {
6971
7167
  if (that.plotheight - getLabelX.call(that, d) < (that.options.labelSize || that.options.fontSize)) {
@@ -7693,7 +7889,9 @@ const WebsyDesigns = {
7693
7889
  ResponsiveText,
7694
7890
  WebsyResponsiveText: ResponsiveText,
7695
7891
  WebsyDragDrop,
7696
- DragDrop: WebsyDragDrop
7892
+ DragDrop: WebsyDragDrop,
7893
+ WebsySearch,
7894
+ Search: WebsySearch
7697
7895
  }
7698
7896
 
7699
7897
  WebsyDesigns.service = new WebsyDesigns.APIService('')