@websy/websy-designs 1.2.5 → 1.2.7

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.
@@ -26,6 +26,7 @@
26
26
  WebsyCarousel
27
27
  WebsyLogin
28
28
  WebsySignup
29
+ ResponsiveText
29
30
  Pager
30
31
  */
31
32
 
@@ -390,16 +391,20 @@ class WebsyDatePicker {
390
391
  this.currentselection = []
391
392
  this.validDates = []
392
393
  this.validYears = []
394
+ this.validHours = []
393
395
  this.customRangeSelected = true
394
396
  this.shiftPressed = false
395
397
  const DEFAULTS = {
396
398
  defaultRange: 0,
397
399
  allowClear: true,
400
+ hideRanges: false,
398
401
  minAllowedDate: this.floorDate(new Date(new Date((new Date().setFullYear(new Date().getFullYear() - 1))).setDate(1))),
399
402
  maxAllowedDate: this.floorDate(new Date((new Date()))),
400
403
  minAllowedYear: 1970,
401
404
  maxAllowedYear: new Date().getFullYear(),
402
405
  daysOfWeek: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
406
+ monthsOfYear: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
407
+ hours: new Array(24).fill(0).map((d, i) => ({text: (i < 10 ? '0' : '') + i + ':00', num: (1 / 24 * i)})),
403
408
  mode: 'date',
404
409
  monthMap: {
405
410
  0: 'Jan',
@@ -465,6 +470,30 @@ class WebsyDatePicker {
465
470
  label: 'Last 10 Years',
466
471
  range: [new Date().getFullYear() - 9, DEFAULTS.maxAllowedYear]
467
472
  }
473
+ ],
474
+ monthyear: [
475
+ {
476
+ label: 'All',
477
+ range: [DEFAULTS.minAllowedDate, DEFAULTS.maxAllowedDate]
478
+ },
479
+ {
480
+ label: 'Last 12 Months',
481
+ range: [this.floorDate(new Date(new Date(new Date().setDate(1)).setMonth(new Date().getMonth() - 12))), this.floorDate(new Date(new Date().setDate(1)))]
482
+ },
483
+ {
484
+ label: 'Last 18 Months',
485
+ range: [this.floorDate(new Date(new Date(new Date().setDate(1)).setMonth(new Date().getMonth() - 18))), this.floorDate(new Date(new Date().setDate(1)))]
486
+ },
487
+ {
488
+ label: 'Last 24 Months',
489
+ range: [this.floorDate(new Date(new Date(new Date().setDate(1)).setMonth(new Date().getMonth() - 24))), this.floorDate(new Date(new Date().setDate(1)))]
490
+ }
491
+ ],
492
+ hour: [
493
+ {
494
+ label: 'All',
495
+ range: ['00:00', '23:00']
496
+ }
468
497
  ]
469
498
  }
470
499
  this.options = Object.assign({}, DEFAULTS, options)
@@ -487,7 +516,7 @@ class WebsyDatePicker {
487
516
  document.addEventListener('keydown', this.handleKeyDown.bind(this))
488
517
  document.addEventListener('keyup', this.handleKeyUp.bind(this))
489
518
  let html = `
490
- <div class='websy-date-picker-container'>
519
+ <div class='websy-date-picker-container ${this.options.mode}'>
491
520
  <span class='websy-dropdown-header-label'>${this.options.label || 'Date'}</span>
492
521
  <div id="${this.elementId}_header" class='websy-date-picker-header ${this.options.allowClear === true ? 'allow-clear' : ''}'>
493
522
  <span id='${this.elementId}_selectedRange'>${this.options.ranges[this.options.mode][this.selectedRange].label}</span>
@@ -501,8 +530,8 @@ class WebsyDatePicker {
501
530
  html += `
502
531
  </div>
503
532
  <div id='${this.elementId}_mask' class='websy-date-picker-mask'></div>
504
- <div id='${this.elementId}_content' class='websy-date-picker-content'>
505
- <div class='websy-date-picker-ranges'>
533
+ <div id='${this.elementId}_content' class='websy-date-picker-content ${this.options.hideRanges === true ? 'hide-ranges' : ''}'>
534
+ <div class='websy-date-picker-ranges' >
506
535
  <ul id='${this.elementId}_rangelist'>
507
536
  ${this.renderRanges()}
508
537
  </ul>
@@ -538,11 +567,28 @@ class WebsyDatePicker {
538
567
  contentEl.classList.remove('active')
539
568
  if (confirm === true) {
540
569
  if (this.options.onChange) {
541
- if (this.customRangeSelected === true) {
542
- this.options.onChange(this.selectedRangeDates, true)
570
+ console.log('confirm', this.selectedRangeDates)
571
+ console.log('confirm', this.currentselection)
572
+ if (this.customRangeSelected === true) {
573
+ if (this.options.mode === 'hour') {
574
+ let hoursOut = []
575
+ for (let i = this.selectedRangeDates[0]; i < this.selectedRangeDates[1] + 1; i++) {
576
+ hoursOut.push(this.options.hours[i])
577
+ }
578
+ this.options.onChange(hoursOut, true)
579
+ }
580
+ else {
581
+ this.options.onChange(this.selectedRangeDates, true)
582
+ }
543
583
  }
544
584
  else {
545
- this.options.onChange(this.currentselection, false)
585
+ if (this.options.mode === 'hour') {
586
+ let hoursOut = this.selectedRangeDates.map(h => this.options.hours[h])
587
+ this.options.onChange(hoursOut, true)
588
+ }
589
+ else {
590
+ this.options.onChange(this.currentselection, false)
591
+ }
546
592
  }
547
593
  }
548
594
  this.updateRange()
@@ -607,7 +653,7 @@ class WebsyDatePicker {
607
653
  handleMouseDown (event) {
608
654
  if (this.shiftPressed === true && this.currentselection.length > 0) {
609
655
  this.mouseDownId = this.currentselection[this.currentselection.length - 1]
610
- this.selectDate(+event.target.id.split('_')[0])
656
+ this.selectDate(+event.target.id.split('_')[1])
611
657
  }
612
658
  else {
613
659
  this.mouseDown = true
@@ -620,7 +666,7 @@ class WebsyDatePicker {
620
666
  this.currentselection = []
621
667
  this.customRangeSelected = false
622
668
  }
623
- this.mouseDownId = +event.target.id.split('_')[0]
669
+ this.mouseDownId = +event.target.id.split('_')[1]
624
670
  this.selectDate(this.mouseDownId)
625
671
  }
626
672
  }
@@ -631,9 +677,9 @@ class WebsyDatePicker {
631
677
  if (event.target.classList.contains('websy-disabled-date')) {
632
678
  return
633
679
  }
634
- if (event.target.id.split('_')[0] !== this.mouseDownId) {
680
+ if (event.target.id.split('_')[1] !== this.mouseDownId) {
635
681
  this.dragging = true
636
- this.selectDate(+event.target.id.split('_')[0])
682
+ this.selectDate(+event.target.id.split('_')[1])
637
683
  }
638
684
  }
639
685
  }
@@ -655,7 +701,8 @@ class WebsyDatePicker {
655
701
  return
656
702
  }
657
703
  if (this.customRangeSelected === true) {
658
- console.log('if date selection', this.currentselection)
704
+ console.log('if date selection', this.currentselection)
705
+ console.log('if month selection', this.currentselection.map(d => new Date(d)))
659
706
  let diff
660
707
  if (this.options.mode === 'date') {
661
708
  diff = Math.floor((this.selectedRangeDates[this.selectedRangeDates.length - 1].getTime() - this.selectedRangeDates[0].getTime()) / this.oneDay)
@@ -669,6 +716,15 @@ class WebsyDatePicker {
669
716
  // diff += 1
670
717
  }
671
718
  }
719
+ else if (this.options.mode === 'monthyear') {
720
+ let yearDiff = (this.selectedRangeDates[this.selectedRangeDates.length - 1].getFullYear() - this.selectedRangeDates[0].getFullYear()) * 12
721
+ diff = Math.floor((this.selectedRangeDates[this.selectedRangeDates.length - 1].getMonth() - this.selectedRangeDates[0].getMonth())) + yearDiff
722
+ console.log('year diff', yearDiff)
723
+ console.log('diff', diff)
724
+ }
725
+ else if (this.options.mode === 'hour') {
726
+ diff = this.selectedRangeDates[this.selectedRangeDates.length - 1] - this.selectedRangeDates[0]
727
+ }
672
728
  for (let i = 0; i < diff + 1; i++) {
673
729
  let d
674
730
  let rangeStart
@@ -684,12 +740,31 @@ class WebsyDatePicker {
684
740
  rangeStart = this.selectedRangeDates[0]
685
741
  rangeEnd = this.selectedRangeDates[this.selectedRangeDates.length - 1]
686
742
  }
743
+ else if (this.options.mode === 'monthyear') {
744
+ d = new Date(this.selectedRangeDates[0].getTime()).setMonth(this.selectedRangeDates[0].getMonth() + i)
745
+ rangeStart = this.selectedRangeDates[0].getTime()
746
+ rangeEnd = this.selectedRangeDates[this.selectedRangeDates.length - 1].getTime()
747
+ }
748
+ else if (this.options.mode === 'hour') {
749
+ d = this.selectedRangeDates[0] + i
750
+ rangeStart = this.selectedRangeDates[0]
751
+ rangeEnd = this.selectedRangeDates[this.selectedRangeDates.length - 1]
752
+ }
687
753
  let dateEl
688
754
  if (this.options.mode === 'date') {
689
- dateEl = document.getElementById(`${d}_date`)
755
+ dateEl = document.getElementById(`${this.elementId}_${d}_date`)
690
756
  }
691
757
  else if (this.options.mode === 'year') {
692
- dateEl = document.getElementById(`${d}_year`)
758
+ dateEl = document.getElementById(`${this.elementId}_${d}_year`)
759
+ }
760
+ else if (this.options.mode === 'monthyear') {
761
+ console.log('d', d)
762
+ console.log(this.selectedRangeDates)
763
+ console.log(rangeStart, rangeEnd)
764
+ dateEl = document.getElementById(`${this.elementId}_${d}_monthyear`)
765
+ }
766
+ else if (this.options.mode === 'hour') {
767
+ dateEl = document.getElementById(`${this.elementId}_${d}_hour`)
693
768
  }
694
769
  if (dateEl) {
695
770
  dateEl.classList.add('selected')
@@ -706,10 +781,16 @@ class WebsyDatePicker {
706
781
  this.currentselection.forEach(d => {
707
782
  let dateEl
708
783
  if (this.options.mode === 'date') {
709
- dateEl = document.getElementById(`${d}_date`)
784
+ dateEl = document.getElementById(`${this.elementId}_${d}_date`)
710
785
  }
711
786
  else if (this.options.mode === 'year') {
712
- dateEl = document.getElementById(`${d}_year`)
787
+ dateEl = document.getElementById(`${this.elementId}_${d}_year`)
788
+ }
789
+ else if (this.options.mode === 'monthyear') {
790
+ dateEl = document.getElementById(`${this.elementId}_${d}_monthyear`)
791
+ }
792
+ else if (this.options.mode === 'hour') {
793
+ dateEl = document.getElementById(`${this.elementId}_${d}_hour`)
713
794
  }
714
795
  dateEl.classList.add('selected')
715
796
  dateEl.classList.add('first')
@@ -751,6 +832,9 @@ class WebsyDatePicker {
751
832
  let disabled = []
752
833
  this.validDates = []
753
834
  this.validYears = []
835
+ this.validHours = []
836
+ this.monthYears = {}
837
+ this.monthYearMonths = []
754
838
  if (disabledDates) {
755
839
  disabled = disabledDates.map(d => {
756
840
  if (this.options.mode === 'date') {
@@ -759,6 +843,12 @@ class WebsyDatePicker {
759
843
  else if (this.options.mode === 'year') {
760
844
  return d
761
845
  }
846
+ else if (this.options.mode === 'monthyear') {
847
+ //
848
+ }
849
+ else if (this.options.mode === 'hour') {
850
+ return d
851
+ }
762
852
  return d.getTime()
763
853
  })
764
854
  }
@@ -771,15 +861,34 @@ class WebsyDatePicker {
771
861
  else if (this.options.mode === 'year') {
772
862
  diff = (this.options.maxAllowedYear - this.options.minAllowedYear) + 1
773
863
  }
864
+ else if (this.options.mode === 'monthyear') {
865
+ diff = Math.ceil((this.options.maxAllowedDate.getTime() - this.options.minAllowedDate.getTime()) / this.oneDay) + 1
866
+ }
867
+ else if (this.options.mode === 'hour') {
868
+ diff = 24
869
+ }
774
870
  let months = {}
775
871
  let yearList = []
776
872
  for (let i = 0; i < diff; i++) {
777
- if (this.options.mode === 'date') {
873
+ if (this.options.mode === 'date' || this.options.mode === 'monthyear') {
778
874
  let d = this.floorDate(new Date(this.options.minAllowedDate.getTime() + (i * this.oneDay)))
779
875
  let monthYear = `${this.options.monthMap[d.getMonth()]} ${d.getFullYear()}`
780
876
  if (!months[monthYear]) {
781
877
  months[monthYear] = []
782
878
  }
879
+ if (!this.monthYears[d.getFullYear()]) {
880
+ this.monthYears[d.getFullYear()] = []
881
+ }
882
+ if (this.monthYearMonths.indexOf(`${d.getMonth()}-${d.getFullYear()}`) === -1) {
883
+ this.monthYearMonths.push(`${d.getMonth()}-${d.getFullYear()}`)
884
+ this.monthYears[d.getFullYear()].push({
885
+ date: new Date(d.setDate(1)),
886
+ month: this.options.monthMap[d.getMonth()],
887
+ monthNum: d.getMonth(),
888
+ year: d.getFullYear(),
889
+ id: d.setDate(1)
890
+ })
891
+ }
783
892
  if (disabled.indexOf(d.getTime()) === -1) {
784
893
  this.validDates.push(d.getTime())
785
894
  }
@@ -792,11 +901,21 @@ class WebsyDatePicker {
792
901
  this.validYears.push(d)
793
902
  }
794
903
  }
904
+ else if (this.options.mode === 'hour') {
905
+ //
906
+ }
795
907
  }
908
+ if (this.options.mode === 'hour') {
909
+ this.options.hours.forEach(h => {
910
+ if (disabled.indexOf(h.text) === -1) {
911
+ this.validHours.push(h)
912
+ }
913
+ })
914
+ }
796
915
  // check each range to see if it can be enabled
797
916
  for (let i = 0; i < this.options.ranges[this.options.mode].length; i++) {
798
917
  const r = this.options.ranges[this.options.mode][i]
799
- if (this.options.mode === 'date') {
918
+ if (this.options.mode === 'date' || this.options.mode === 'monthyear') {
800
919
  // check the first date
801
920
  if (this.validDates.indexOf(r.range[0].getTime()) !== -1) {
802
921
  r.disabled = false
@@ -836,6 +955,28 @@ class WebsyDatePicker {
836
955
  }
837
956
  }
838
957
  }
958
+ }
959
+ else if (this.options.mode === 'monthyear') {
960
+ //
961
+ }
962
+ else if (this.options.mode === 'hour') {
963
+ if (this.validDates.indexOf(r.range[0]) !== -1) {
964
+ r.disabled = false
965
+ }
966
+ else if (r.range[1]) {
967
+ if (this.validDates.indexOf(r.range[1]) !== -1) {
968
+ r.disabled = false
969
+ }
970
+ else {
971
+ // check the full range until a match is found
972
+ for (let i = r.range[0]; i <= r.range[1]; i++) {
973
+ if (this.validDates.indexOf(r.range[0] + i) !== -1) {
974
+ r.disabled = false
975
+ break
976
+ }
977
+ }
978
+ }
979
+ }
839
980
  }
840
981
  }
841
982
  let html = ''
@@ -861,7 +1002,7 @@ class WebsyDatePicker {
861
1002
  }
862
1003
  html += paddedDays.join('')
863
1004
  }
864
- html += months[key].map(d => `<li id='${d.id}_date' class='websy-dp-date ${d.disabled === true ? 'websy-disabled-date' : ''}'>${d.dayOfMonth}</li>`).join('')
1005
+ 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('')
865
1006
  html += `
866
1007
  </ul>
867
1008
  </div>
@@ -874,7 +1015,31 @@ class WebsyDatePicker {
874
1015
  yearList.reverse()
875
1016
  }
876
1017
  html += `<div id='${this.elementId}_dateList' class='websy-dp-date-list'><ul>`
877
- html += yearList.map(d => `<li id='${d.id}_year' class='websy-dp-date websy-dp-year ${d.disabled === true ? 'websy-disabled-date' : ''}'>${d.year}</li>`).join('')
1018
+ 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('')
1019
+ html += `</ul></div>`
1020
+ }
1021
+ else if (this.options.mode === 'monthyear') {
1022
+ html += `<div id='${this.elementId}_dateList' class='websy-dp-monthyear-container'>`
1023
+ for (const year in this.monthYears) {
1024
+ html += `
1025
+ <ul>
1026
+ <li>${year}</li>
1027
+ `
1028
+ if (this.monthYears[year][0].monthNum > 0) {
1029
+ let paddedMonths = []
1030
+ for (let i = 0; i < this.monthYears[year][0].monthNum; i++) {
1031
+ paddedMonths.push(`<li>&nbsp;</li>`)
1032
+ }
1033
+ html += paddedMonths.join('')
1034
+ }
1035
+ 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('')
1036
+ html += `</ul>`
1037
+ }
1038
+ html += `</div>`
1039
+ }
1040
+ else if (this.options.mode === 'hour') {
1041
+ html += `<div id='${this.elementId}_dateList' class='websy-dp-date-list'><ul>`
1042
+ html += this.options.hours.map(h => `<li id='${this.elementId}_${+h.text.split(':')[0]}_hour' data-hour='${h.text}' class='websy-dp-date websy-dp-hour'>${h.text}</li>`).join('')
878
1043
  html += `</ul></div>`
879
1044
  }
880
1045
  return html
@@ -888,16 +1053,22 @@ class WebsyDatePicker {
888
1053
  if (this.selectedRangeDates[0]) {
889
1054
  let el
890
1055
  if (this.options.mode === 'date') {
891
- el = document.getElementById(`${this.selectedRangeDates[0].getTime()}_date`)
1056
+ el = document.getElementById(`${this.elementId}_${this.selectedRangeDates[0].getTime()}_date`)
892
1057
  }
893
1058
  else if (this.options.mode === 'year') {
894
1059
  if (this.options.sortDirection === 'desc') {
895
- el = document.getElementById(`${this.selectedRangeDates[this.selectedRangeDates.length - 1]}_year`)
1060
+ el = document.getElementById(`${this.elementId}_${this.selectedRangeDates[this.selectedRangeDates.length - 1]}_year`)
896
1061
  }
897
1062
  else {
898
- el = document.getElementById(`${this.selectedRangeDates[0]}_year`)
1063
+ el = document.getElementById(`${this.elementId}_${this.selectedRangeDates[0]}_year`)
899
1064
  }
900
1065
  }
1066
+ else if (this.options.mode === 'monthyear') {
1067
+ //
1068
+ }
1069
+ else if (this.options.mode === 'hour') {
1070
+ //
1071
+ }
901
1072
  const parentEl = document.getElementById(`${this.elementId}_dateList`)
902
1073
  if (el && parentEl) {
903
1074
  parentEl.scrollTo(0, el.offsetTop)
@@ -918,19 +1089,33 @@ class WebsyDatePicker {
918
1089
  this.currentselection.splice(0, 0, timestamp)
919
1090
  }
920
1091
  this.customRangeSelected = true
1092
+ console.log('current selection', this.currentselection)
921
1093
  }
922
1094
  else {
923
- this.currentselection.push(timestamp)
1095
+ let index = this.currentselection.indexOf(timestamp)
1096
+ if (index !== -1) {
1097
+ this.currentselection.splice(index, 1)
1098
+ }
1099
+ else {
1100
+ this.currentselection.push(timestamp)
1101
+ }
924
1102
  this.currentselection.sort((a, b) => a - b)
925
1103
  this.customRangeSelected = false
926
1104
  }
927
1105
  }
928
- if (this.options.mode === 'date') {
1106
+ if (this.options.mode === 'date' || this.options.mode === 'monthyear') {
929
1107
  this.selectedRangeDates = [new Date(this.currentselection[0]), new Date(this.currentselection[1] || this.currentselection[0])]
1108
+ console.log('selected range', this.selectedRangeDates)
930
1109
  }
931
1110
  else if (this.options.mode === 'year') {
932
1111
  this.selectedRangeDates = [this.currentselection[0], this.currentselection[1] || this.currentselection[0]]
933
1112
  }
1113
+ else if (this.options.mode === 'monthyear') {
1114
+ //
1115
+ }
1116
+ else if (this.options.mode === 'hour') {
1117
+ this.selectedRangeDates = [this.currentselection[0], this.currentselection[1] || this.currentselection[0]]
1118
+ }
934
1119
  // if (this.currentselection.length === 2) {
935
1120
  // this.currentselection = []
936
1121
  // }
@@ -977,7 +1162,7 @@ class WebsyDatePicker {
977
1162
  this.updateRange()
978
1163
  }
979
1164
  setDateBounds (range) {
980
- if (['All Dates', 'All Years'].indexOf(this.options.ranges[this.options.mode][0].label) !== -1) {
1165
+ if (['All Dates', 'All Years', 'All'].indexOf(this.options.ranges[this.options.mode][0].label) !== -1) {
981
1166
  this.options.ranges[this.options.mode][0].range = [range[0], range[1] || range[0]]
982
1167
  }
983
1168
  if (this.options.mode === 'date') {
@@ -987,6 +1172,14 @@ class WebsyDatePicker {
987
1172
  else if (this.options.mode === 'year') {
988
1173
  this.options.minAllowedYear = range[0]
989
1174
  this.options.maxAllowedYear = range[1] || range[0]
1175
+ }
1176
+ else if (this.options.mode === 'monthyear') {
1177
+ this.options.minAllowedDate = range[0]
1178
+ this.options.maxAllowedDate = range[1] || range[0]
1179
+ }
1180
+ else if (this.options.mode === 'hour') {
1181
+ this.options.minAllowedHour = range[0]
1182
+ this.options.maxAllowedHour = range[1] || range[0]
990
1183
  }
991
1184
  }
992
1185
  updateRange () {
@@ -1002,6 +1195,15 @@ class WebsyDatePicker {
1002
1195
  else if (this.options.mode === 'year') {
1003
1196
  return d
1004
1197
  }
1198
+ else if (this.options.mode === 'monthyear') {
1199
+ if (!d.getMonth) {
1200
+ d = new Date(d)
1201
+ }
1202
+ return `${this.options.monthMap[d.getMonth()]} ${d.getFullYear()}`
1203
+ }
1204
+ else if (this.options.mode === 'hour') {
1205
+ return d
1206
+ }
1005
1207
  })
1006
1208
  let start = list[0]
1007
1209
  let end = ''
@@ -1011,6 +1213,10 @@ class WebsyDatePicker {
1011
1213
  else {
1012
1214
  start = `${list.length} selected`
1013
1215
  }
1216
+ if (this.options.mode === 'hour') {
1217
+ start = this.options.hours[start].text
1218
+ end = `${this.customRangeSelected === true ? ' - ' : ''}${this.options.hours[list[list.length - 1]].text}`
1219
+ }
1014
1220
  range = { label: `${start}${end}` }
1015
1221
  }
1016
1222
  else {
@@ -1048,7 +1254,8 @@ class WebsyDropdown {
1048
1254
  disabled: false,
1049
1255
  minSearchCharacters: 2,
1050
1256
  showCompleteSelectedList: false,
1051
- closeAfterSelection: true
1257
+ closeAfterSelection: true,
1258
+ customActions: []
1052
1259
  }
1053
1260
  this.options = Object.assign({}, DEFAULTS, options)
1054
1261
  if (this.options.items.length > 0) {
@@ -1074,7 +1281,7 @@ class WebsyDropdown {
1074
1281
  const headerLabel = this.selectedItems.map(s => this.options.items[s].label || this.options.items[s].value).join(this.options.multiValueDelimiter)
1075
1282
  const headerValue = this.selectedItems.map(s => this.options.items[s].value || this.options.items[s].label).join(this.options.multiValueDelimiter)
1076
1283
  let html = `
1077
- <div id='${this.elementId}_container' class='websy-dropdown-container ${this.options.disabled ? 'disabled' : ''} ${this.options.disableSearch !== true ? 'with-search' : ''} ${this.options.style}'>
1284
+ <div id='${this.elementId}_container' class='websy-dropdown-container ${this.options.disabled ? 'disabled' : ''} ${this.options.disableSearch !== true ? 'with-search' : ''} ${this.options.style} ${this.options.customActions.length > 0 ? 'with-actions' : ''}'>
1078
1285
  <div id='${this.elementId}_header' class='websy-dropdown-header ${this.selectedItems.length === 1 ? 'one-selected' : ''} ${this.options.allowClear === true ? 'allow-clear' : ''}'>
1079
1286
  <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>
1080
1287
  <span id='${this.elementId}_headerLabel' class='websy-dropdown-header-label'>${this.options.label}</span>
@@ -1092,6 +1299,24 @@ class WebsyDropdown {
1092
1299
  <div id='${this.elementId}_mask' class='websy-dropdown-mask'></div>
1093
1300
  <div id='${this.elementId}_content' class='websy-dropdown-content'>
1094
1301
  `
1302
+ if (this.options.customActions.length > 0) {
1303
+ html += `
1304
+ <div class='websy-dropdown-action-container'>
1305
+ <button class='websy-dropdown-action-button'>
1306
+ <svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 512 512">><circle cx="256" cy="256" r="32" style="fill:none;stroke:#000;stroke-miterlimit:10;stroke-width:32px"/><circle cx="416" cy="256" r="32" style="fill:none;stroke:#000;stroke-miterlimit:10;stroke-width:32px"/><circle cx="96" cy="256" r="32" style="fill:none;stroke:#000;stroke-miterlimit:10;stroke-width:32px"/></svg>
1307
+ </button>
1308
+ <ul id='${this.elementId}_actionContainer'>
1309
+ `
1310
+ this.options.customActions.forEach((a, i) => {
1311
+ html += `
1312
+ <li class='websy-dropdown-custom-action' data-index='${i}'>${a.label}</li>
1313
+ `
1314
+ })
1315
+ html += `
1316
+ </ul>
1317
+ </div>
1318
+ `
1319
+ }
1095
1320
  if (this.options.disableSearch !== true) {
1096
1321
  html += `
1097
1322
  <input id='${this.elementId}_search' class='websy-dropdown-search' placeholder='${this.options.searchPlaceholder || 'Search'}'>
@@ -1153,6 +1378,10 @@ class WebsyDropdown {
1153
1378
  const maskEl = document.getElementById(`${this.elementId}_mask`)
1154
1379
  const contentEl = document.getElementById(`${this.elementId}_content`)
1155
1380
  const scrollEl = document.getElementById(`${this.elementId}_itemsContainer`)
1381
+ const actionEl = document.getElementById(`${this.elementId}_actionContainer`)
1382
+ if (actionEl) {
1383
+ actionEl.classList.remove('active')
1384
+ }
1156
1385
  const el = document.getElementById(this.elementId)
1157
1386
  if (el) {
1158
1387
  el.style.zIndex = ''
@@ -1193,6 +1422,18 @@ class WebsyDropdown {
1193
1422
  const el = document.getElementById(`${this.elementId}_container`)
1194
1423
  el.classList.toggle('search-open')
1195
1424
  }
1425
+ else if (event.target.classList.contains('websy-dropdown-custom-action')) {
1426
+ const actionIndex = +event.target.getAttribute('data-index')
1427
+ if (this.options.customActions[actionIndex] && this.options.customActions[actionIndex].fn) {
1428
+ this.options.customActions[actionIndex].fn()
1429
+ }
1430
+ }
1431
+ else if (event.target.classList.contains('websy-dropdown-action-button')) {
1432
+ const el = document.getElementById(`${this.elementId}_actionContainer`)
1433
+ if (el) {
1434
+ el.classList.toggle('active')
1435
+ }
1436
+ }
1196
1437
  }
1197
1438
  handleKeyUp (event) {
1198
1439
  if (event.target.classList.contains('websy-dropdown-search')) {
@@ -2429,6 +2670,250 @@ class WebsyPubSub {
2429
2670
  }
2430
2671
  }
2431
2672
 
2673
+ class ResponsiveText {
2674
+ constructor (elementId, options) {
2675
+ const DEFAULTS = {
2676
+ textAlign: 'center',
2677
+ verticalAlign: 'flex-end',
2678
+ wrapText: false
2679
+ }
2680
+ this.options = Object.assign({}, DEFAULTS, options)
2681
+ this.elementId = elementId
2682
+ this.canvas = document.createElement('canvas')
2683
+ window.addEventListener('resize', () => this.render())
2684
+ const el = document.getElementById(this.elementId)
2685
+ if (el) {
2686
+ this.render()
2687
+ }
2688
+ }
2689
+ css (element, property) {
2690
+ return window.getComputedStyle(element, null).getPropertyValue(property)
2691
+ }
2692
+ render (text) {
2693
+ if (typeof text !== 'undefined') {
2694
+ this.options.text = text
2695
+ }
2696
+ if (this.options.text) {
2697
+ let wrappingRequired = false
2698
+ const el = document.getElementById(this.elementId)
2699
+ let cx = this.canvas.getContext('2d')
2700
+ let f = 0
2701
+ let fits = false
2702
+ // let el = document.getElementById(`${layout.qInfo.qId}_responsiveInner`)
2703
+ let height = el.clientHeight
2704
+ if (typeof this.options.maxHeight === 'string' && this.options.maxHeight.indexOf('%') !== -1) {
2705
+ let p = +this.options.maxHeight.replace('%', '')
2706
+ if (!isNaN(p)) {
2707
+ this.options.maxHeight = Math.floor(height * (p / 100))
2708
+ }
2709
+ }
2710
+ else if (
2711
+ typeof this.options.maxHeight === 'string' &&
2712
+ this.options.maxHeight.indexOf('px') !== -1
2713
+ ) {
2714
+ this.options.maxHeight = +this.options.maxHeight.replace('px', '')
2715
+ }
2716
+ if (typeof this.options.minHeight === 'string' && this.options.minHeight.indexOf('%') !== -1) {
2717
+ let p = +this.options.minHeight.replace('%', '')
2718
+ if (!isNaN(p)) {
2719
+ this.options.minHeight = Math.floor(height * (p / 100))
2720
+ }
2721
+ }
2722
+ else if (
2723
+ typeof this.options.minHeight === 'string' &&
2724
+ this.options.minHeight.indexOf('px') !== -1
2725
+ ) {
2726
+ this.options.minHeight = +this.options.minHeight.replace('px', '')
2727
+ }
2728
+
2729
+ const fontFamily = this.css(el, 'font-family')
2730
+ const fontWeight = this.css(el, 'font-weight')
2731
+ let allowedWidth = el.clientWidth
2732
+ if (allowedWidth === 0) {
2733
+ // check for a max-width property
2734
+ if (
2735
+ el.style.maxWidth &&
2736
+ el.style.maxWidth !== 'auto'
2737
+ ) {
2738
+ if (el.parentElement.clientWidth > 0) {
2739
+ let calc = el.style.maxWidth
2740
+ if (calc.indexOf('calc') !== -1) {
2741
+ // this logic currently only handles calc statements using % and px
2742
+ // and only + or - formulas
2743
+ calc = calc.replace('calc(', '').replace(')', '')
2744
+ calc = calc.split(' ')
2745
+ if (calc[0].indexOf('px') !== -1) {
2746
+ allowedWidth = calc[0].replace('px', '')
2747
+ }
2748
+ else if (calc[0].indexOf('%') !== -1) {
2749
+ allowedWidth = el.parentElement.clientWidth * (+calc[0].replace('%', '') / 100)
2750
+ }
2751
+ if (calc[2] && calc[4]) {
2752
+ // this means we have an operator and a second value
2753
+ // handle -
2754
+ if (calc[2] === '-') {
2755
+ if (calc[4].indexOf('px') !== -1) {
2756
+ allowedWidth -= +calc[4].replace('px', '')
2757
+ }
2758
+ }
2759
+ if (calc[2] === '+') {
2760
+ if (calc[4].indexOf('px') !== -1) {
2761
+ allowedWidth += +calc[4].replace('px', '')
2762
+ }
2763
+ }
2764
+ }
2765
+ }
2766
+ else if (calc.indexOf('px') !== -1) {
2767
+ allowedWidth = +calc.replace('px', '')
2768
+ }
2769
+ else if (calc.indexOf('%') !== -1) {
2770
+ allowedWidth =
2771
+ el.parentElement.clientWidth *
2772
+ (+calc.replace('%', '') / 100)
2773
+ }
2774
+ }
2775
+ }
2776
+ }
2777
+ // console.log('max height', this.options.maxHeight);
2778
+ let innerElHeight = el.clientHeight
2779
+ while (fits === false) {
2780
+ f++
2781
+ cx.font = `${fontWeight} ${f}px ${fontFamily}`
2782
+ let measurements = cx.measureText(this.options.text)
2783
+ // add support for safari where some elements end up with zero height
2784
+ if (navigator.userAgent.indexOf('Safari') !== -1) {
2785
+ // get the closest parent that has a height
2786
+ let heightFound = false
2787
+ let currEl = el
2788
+ while (heightFound === false) {
2789
+ if (currEl.clientHeight > 0) {
2790
+ innerElHeight = currEl.clientHeight
2791
+ heightFound = true
2792
+ }
2793
+ else if (currEl.parentNode) {
2794
+ currEl = currEl.parentNode
2795
+ }
2796
+ else {
2797
+ // prevent the loop from running indefinitely
2798
+ heightFound = true
2799
+ }
2800
+ }
2801
+ }
2802
+ if (typeof this.options.maxHeight !== 'undefined' && f === this.options.maxHeight) {
2803
+ f = this.options.maxHeight
2804
+ height = measurements.actualBoundingBoxAscent
2805
+ fits = true
2806
+ }
2807
+ else if (
2808
+ measurements.width > allowedWidth ||
2809
+ measurements.actualBoundingBoxAscent >= innerElHeight
2810
+ ) {
2811
+ f--
2812
+ height = measurements.actualBoundingBoxAscent
2813
+ fits = true
2814
+ }
2815
+ }
2816
+ if (this.options.minHeight === '') {
2817
+ this.options.minHeight = undefined
2818
+ }
2819
+ if (typeof this.options.minHeight !== 'undefined') {
2820
+ if (this.options.minHeight > f && this.options.wrapText === true) {
2821
+ // we run the process again but this time separating the words onto separate lines
2822
+ // this currently only supports wrapping onto 2 lines
2823
+ wrappingRequired = true
2824
+ fits = false
2825
+ f = this.options.minHeight
2826
+ let spaceCount = this.options.text.match(/ /g)
2827
+ if (spaceCount && spaceCount.length > 0) {
2828
+ spaceCount = spaceCount.length
2829
+ let words = this.options.text.split(' ')
2830
+ while (fits === false) {
2831
+ f++
2832
+ cx.font = `${fontWeight} ${f}px ${fontFamily}`
2833
+ for (let i = spaceCount; i > 0; i--) {
2834
+ let fitsCount = 0
2835
+ let lines = [
2836
+ words.slice(0, i).join(' '),
2837
+ words.slice(i, words.length).join(' ')
2838
+ ]
2839
+ let longestLine = lines.reduce(
2840
+ (a, b) => (a.length > b.length ? a : b),
2841
+ ''
2842
+ )
2843
+ // lines.forEach(l => {
2844
+ let measurements = cx.measureText(longestLine)
2845
+ // add support for safari where some elements end up with zero height
2846
+ if (navigator.userAgent.indexOf('Safari') !== -1) {
2847
+ // get the closest parent that has a height
2848
+ let heightFound = false
2849
+ let currEl = el
2850
+ while (heightFound === false) {
2851
+ if (currEl.clientHeight > 0) {
2852
+ innerElHeight = currEl.clientHeight
2853
+ heightFound = true
2854
+ }
2855
+ else if (currEl.parentNode) {
2856
+ currEl = currEl.parentNode
2857
+ }
2858
+ else {
2859
+ // prevent the loop from running indefinitely
2860
+ heightFound = true
2861
+ }
2862
+ }
2863
+ }
2864
+ if (typeof this.options.maxHeight !== 'undefined' && f === this.options.maxHeight) {
2865
+ f = this.options.maxHeight
2866
+ height = measurements.actualBoundingBoxAscent
2867
+ fits = true
2868
+ break
2869
+ }
2870
+ else if (
2871
+ measurements.width > allowedWidth ||
2872
+ measurements.actualBoundingBoxAscent >=
2873
+ (innerElHeight / 2) * 0.75
2874
+ ) {
2875
+ f--
2876
+ height = measurements.actualBoundingBoxAscent
2877
+ fits = true
2878
+ break
2879
+ }
2880
+ // })
2881
+ }
2882
+ }
2883
+ }
2884
+ if (typeof this.options.minHeight !== 'undefined' && this.options.minHeight > f) {
2885
+ f = this.options.minHeight
2886
+ }
2887
+ }
2888
+ else if (this.options.minHeight > f) {
2889
+ f = this.options.minHeight
2890
+ }
2891
+ }
2892
+ let spanHeight = Math.min(innerElHeight, height)
2893
+ el.innerHTML = `
2894
+ <div
2895
+ class='websy-responsive-text'
2896
+ style='
2897
+ justify-content: ${this.options.verticalAlign};
2898
+ font-size: ${f}px;
2899
+ font-weight: ${fontWeight || 'normal'};
2900
+ '
2901
+ >
2902
+ <span
2903
+ style='
2904
+ white-space: ${this.options.wrapText === true ? 'normal' : 'nowrap'};
2905
+ height: ${Math.floor(wrappingRequired === true ? spanHeight * ((1 * 1) / 3) * 2 : spanHeight)}px;
2906
+ line-height: ${Math.ceil(wrappingRequired === true ? f * 1.2 : spanHeight)}px;
2907
+ justify-content: ${this.options.textAlign};
2908
+ text-align: ${this.options.textAlign};
2909
+ '
2910
+ >${this.options.text}</span>
2911
+ </div>
2912
+ `
2913
+ }
2914
+ }
2915
+ }
2916
+
2432
2917
  /* global WebsyDesigns */
2433
2918
  class WebsyResultList {
2434
2919
  constructor (elementId, options) {
@@ -4268,7 +4753,9 @@ class WebsyTable2 {
4268
4753
  handleGlobalMouseUp (event) {
4269
4754
  this.scrolling = false
4270
4755
  const el = document.getElementById(this.elementId)
4271
- el.classList.remove('scrolling')
4756
+ if (el) {
4757
+ el.classList.remove('scrolling')
4758
+ }
4272
4759
  }
4273
4760
  handleMouseUp (event) {
4274
4761
  this.scrolling = false
@@ -5988,7 +6475,7 @@ class WebsyMap {
5988
6475
  const el = document.getElementById(this.elementId)
5989
6476
  if (el) {
5990
6477
  if (typeof d3 === 'undefined') {
5991
- console.error('d3 library has not been loaded')
6478
+ // console.error('d3 library has not been loaded')
5992
6479
  }
5993
6480
  if (typeof L === 'undefined') {
5994
6481
  console.error('Leaflet library has not been loaded')
@@ -6281,7 +6768,9 @@ const WebsyDesigns = {
6281
6768
  WebsyLogin,
6282
6769
  Login: WebsyLogin,
6283
6770
  WebsySignup,
6284
- Signup: WebsySignup
6771
+ Signup: WebsySignup,
6772
+ ResponsiveText,
6773
+ WebsyResponsiveText: ResponsiveText
6285
6774
  }
6286
6775
 
6287
6776
  WebsyDesigns.service = new WebsyDesigns.APIService('')