@websy/websy-designs 1.0.3 → 1.1.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.
@@ -10,6 +10,7 @@
10
10
  WebsyRouter
11
11
  WebsyResultList
12
12
  WebsyTable
13
+ WebsyTable2
13
14
  WebsyChart
14
15
  WebsyChartTooltip
15
16
  WebsyLegend
@@ -21,6 +22,7 @@
21
22
  APIService
22
23
  ButtonGroup
23
24
  WebsyUtils
25
+ Pager
24
26
  */
25
27
 
26
28
  /* global XMLHttpRequest fetch ENV */
@@ -200,11 +202,16 @@ class WebsyDatePicker {
200
202
  this.oneDay = 1000 * 60 * 60 * 24
201
203
  this.currentselection = []
202
204
  this.validDates = []
205
+ this.validYears = []
206
+ this.customRangeSelected = true
203
207
  const DEFAULTS = {
204
208
  defaultRange: 0,
205
209
  minAllowedDate: this.floorDate(new Date(new Date((new Date().setFullYear(new Date().getFullYear() - 1))).setDate(1))),
206
210
  maxAllowedDate: this.floorDate(new Date((new Date()))),
211
+ minAllowedYear: 1970,
212
+ maxAllowedYear: new Date().getFullYear(),
207
213
  daysOfWeek: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
214
+ mode: 'date',
208
215
  monthMap: {
209
216
  0: 'Jan',
210
217
  1: 'Feb',
@@ -221,44 +228,62 @@ class WebsyDatePicker {
221
228
  },
222
229
  ranges: []
223
230
  }
224
- DEFAULTS.ranges = [
225
- {
226
- label: 'All Dates',
227
- range: [DEFAULTS.minAllowedDate, DEFAULTS.maxAllowedDate]
228
- },
229
- {
230
- label: 'Today',
231
- range: [this.floorDate(new Date())]
232
- },
233
- {
234
- label: 'Yesterday',
235
- range: [this.floorDate(new Date().setDate(new Date().getDate() - 1))]
236
- },
237
- {
238
- label: 'Last 7 Days',
239
- range: [this.floorDate(new Date().setDate(new Date().getDate() - 6)), this.floorDate(new Date())]
240
- },
241
- {
242
- label: 'This Month',
243
- range: [this.floorDate(new Date().setDate(1)), this.floorDate(new Date(new Date().setDate(1)).setMonth(new Date().getMonth() + 1) - this.oneDay)]
244
- },
245
- {
246
- label: 'Last Month',
247
- range: [this.floorDate(new Date(new Date().setDate(1)).setMonth(new Date().getMonth() - 1)), this.floorDate(new Date(new Date().setDate(1)).setMonth(new Date().getMonth()) - this.oneDay)]
248
- },
249
- {
250
- label: 'This Year',
251
- range: [this.floorDate(new Date(`1/1/${new Date().getFullYear()}`)), this.floorDate(new Date(`12/31/${new Date().getFullYear()}`))]
252
- },
253
- {
254
- label: 'Last Year',
255
- range: [this.floorDate(new Date(`1/1/${new Date().getFullYear() - 1}`)), this.floorDate(new Date(`12/31/${new Date().getFullYear() - 1}`))]
256
- }
257
- ]
231
+ DEFAULTS.ranges = {
232
+ date: [
233
+ {
234
+ label: 'All Dates',
235
+ range: [DEFAULTS.minAllowedDate, DEFAULTS.maxAllowedDate]
236
+ },
237
+ {
238
+ label: 'Today',
239
+ range: [this.floorDate(new Date())]
240
+ },
241
+ {
242
+ label: 'Yesterday',
243
+ range: [this.floorDate(new Date().setDate(new Date().getDate() - 1))]
244
+ },
245
+ {
246
+ label: 'Last 7 Days',
247
+ range: [this.floorDate(new Date().setDate(new Date().getDate() - 6)), this.floorDate(new Date())]
248
+ },
249
+ {
250
+ label: 'This Month',
251
+ range: [this.floorDate(new Date().setDate(1)), this.floorDate(new Date(new Date().setDate(1)).setMonth(new Date().getMonth() + 1) - this.oneDay)]
252
+ },
253
+ {
254
+ label: 'Last Month',
255
+ range: [this.floorDate(new Date(new Date().setDate(1)).setMonth(new Date().getMonth() - 1)), this.floorDate(new Date(new Date().setDate(1)).setMonth(new Date().getMonth()) - this.oneDay)]
256
+ },
257
+ {
258
+ label: 'This Year',
259
+ range: [this.floorDate(new Date(`1/1/${new Date().getFullYear()}`)), this.floorDate(new Date(`12/31/${new Date().getFullYear()}`))]
260
+ },
261
+ {
262
+ label: 'Last Year',
263
+ range: [this.floorDate(new Date(`1/1/${new Date().getFullYear() - 1}`)), this.floorDate(new Date(`12/31/${new Date().getFullYear() - 1}`))]
264
+ }
265
+ ],
266
+ year: [
267
+ {
268
+ label: 'All Years',
269
+ range: [DEFAULTS.minAllowedYear, DEFAULTS.maxAllowedYear]
270
+ },
271
+ {
272
+ label: 'Last 5 Years',
273
+ range: [new Date().getFullYear() - 4, DEFAULTS.maxAllowedYear]
274
+ },
275
+ {
276
+ label: 'Last 10 Years',
277
+ range: [new Date().getFullYear() - 9, DEFAULTS.maxAllowedYear]
278
+ }
279
+ ]
280
+ }
258
281
  this.options = Object.assign({}, DEFAULTS, options)
259
282
  this.selectedRange = this.options.defaultRange || 0
260
- this.selectedRangeDates = [...this.options.ranges[this.options.defaultRange || 0].range]
283
+ this.selectedRangeDates = [...this.options.ranges[this.options.mode][this.options.defaultRange || 0].range]
261
284
  this.priorSelectedDates = null
285
+ this.priorselection = null
286
+ this.priorCustomRangeSelected = null
262
287
  if (!elementId) {
263
288
  console.log('No element Id provided')
264
289
  return
@@ -267,11 +292,14 @@ class WebsyDatePicker {
267
292
  if (el) {
268
293
  this.elementId = elementId
269
294
  el.addEventListener('click', this.handleClick.bind(this))
295
+ el.addEventListener('mousedown', this.handleMouseDown.bind(this))
296
+ el.addEventListener('mouseover', this.handleMouseOver.bind(this))
297
+ el.addEventListener('mouseup', this.handleMouseUp.bind(this))
270
298
  let html = `
271
299
  <div class='websy-date-picker-container'>
272
300
  <span class='websy-dropdown-header-label'>${this.options.label || 'Date'}</span>
273
301
  <div class='websy-date-picker-header'>
274
- <span id='${this.elementId}_selectedRange'>${this.options.ranges[this.selectedRange].label}</span>
302
+ <span id='${this.elementId}_selectedRange'>${this.options.ranges[this.options.mode][this.selectedRange].label}</span>
275
303
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M23.677 18.52c.914 1.523-.183 3.472-1.967 3.472h-19.414c-1.784 0-2.881-1.949-1.967-3.472l9.709-16.18c.891-1.483 3.041-1.48 3.93 0l9.709 16.18z"/></svg>
276
304
  </div>
277
305
  <div id='${this.elementId}_mask' class='websy-date-picker-mask'></div>
@@ -283,8 +311,12 @@ class WebsyDatePicker {
283
311
  </div><!--
284
312
  --><div id='${this.elementId}_datelist' class='websy-date-picker-custom'>${this.renderDates()}</div>
285
313
  <div class='websy-dp-button-container'>
286
- <button class='websy-btn websy-dp-cancel'>Cancel</button>
287
- <button class='websy-btn websy-dp-confirm'>Confirm</button>
314
+ <button class='${this.options.cancelBtnClasses || ''} websy-btn websy-dp-cancel'>
315
+ <svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 512 512"><line x1="368" y1="368" x2="144" y2="144" style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="368" y1="144" x2="144" y2="368" style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>
316
+ </button>
317
+ <button class='${this.options.confirmBtnClasses || ''} websy-btn websy-dp-confirm'>
318
+ <svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 512 512"><polyline points="416 128 192 384 96 288" style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>
319
+ </button>
288
320
  </div>
289
321
  </div>
290
322
  </div>
@@ -303,13 +335,21 @@ class WebsyDatePicker {
303
335
  contentEl.classList.remove('active')
304
336
  if (confirm === true) {
305
337
  if (this.options.onChange) {
306
- this.options.onChange(this.selectedRangeDates)
338
+ if (this.customRangeSelected === true) {
339
+ this.options.onChange(this.selectedRangeDates, true)
340
+ }
341
+ else {
342
+ this.options.onChange(this.currentselection, false)
343
+ }
307
344
  }
308
345
  this.updateRange()
309
346
  }
310
347
  else {
311
348
  this.selectedRangeDates = [...this.priorSelectedDates]
312
349
  this.selectedRange = this.priorSelectedRange
350
+ this.customRangeSelected = this.priorCustomRangeSelected
351
+ this.currentselection = [...this.priorselection]
352
+ this.highlightRange()
313
353
  }
314
354
  }
315
355
  floorDate (d) {
@@ -334,11 +374,11 @@ class WebsyDatePicker {
334
374
  this.updateRange(index)
335
375
  }
336
376
  else if (event.target.classList.contains('websy-dp-date')) {
337
- if (event.target.classList.contains('websy-disabled-date')) {
338
- return
339
- }
340
- const timestamp = event.target.id.split('_')[0]
341
- this.selectDate(+timestamp)
377
+ // if (event.target.classList.contains('websy-disabled-date')) {
378
+ // return
379
+ // }
380
+ // const timestamp = event.target.id.split('_')[0]
381
+ // this.selectDate(+timestamp)
342
382
  }
343
383
  else if (event.target.classList.contains('websy-dp-confirm')) {
344
384
  this.close(true)
@@ -347,6 +387,39 @@ class WebsyDatePicker {
347
387
  this.close()
348
388
  }
349
389
  }
390
+ handleMouseDown (event) {
391
+ this.mouseDown = true
392
+ this.dragging = false
393
+ if (event.target.classList.contains('websy-dp-date')) {
394
+ if (event.target.classList.contains('websy-disabled-date')) {
395
+ return
396
+ }
397
+ if (this.customRangeSelected === true) {
398
+ this.currentselection = []
399
+ this.customRangeSelected = false
400
+ }
401
+ this.mouseDownId = +event.target.id.split('_')[0]
402
+ this.selectDate(this.mouseDownId)
403
+ }
404
+ }
405
+ handleMouseOver (event) {
406
+ if (this.mouseDown === true) {
407
+ if (event.target.classList.contains('websy-dp-date')) {
408
+ if (event.target.classList.contains('websy-disabled-date')) {
409
+ return
410
+ }
411
+ if (event.target.id.split('_')[0] !== this.mouseDownId) {
412
+ this.dragging = true
413
+ this.selectDate(+event.target.id.split('_')[0])
414
+ }
415
+ }
416
+ }
417
+ }
418
+ handleMouseUp (event) {
419
+ this.mouseDown = false
420
+ this.dragging = false
421
+ this.mouseDownId = null
422
+ }
350
423
  highlightRange () {
351
424
  const el = document.getElementById(`${this.elementId}_dateList`)
352
425
  const dateEls = el.querySelectorAll('.websy-dp-date')
@@ -358,23 +431,67 @@ class WebsyDatePicker {
358
431
  if (this.selectedRange === 0) {
359
432
  return
360
433
  }
361
- let daysDiff = Math.floor((this.selectedRangeDates[this.selectedRangeDates.length - 1].getTime() - this.selectedRangeDates[0].getTime()) / this.oneDay)
362
- if (this.selectedRangeDates[0].getMonth() !== this.selectedRangeDates[this.selectedRangeDates.length - 1].getMonth()) {
363
- daysDiff += 1
364
- }
365
- for (let i = 0; i < daysDiff + 1; i++) {
366
- let d = this.floorDate(new Date(this.selectedRangeDates[0].getTime() + (i * this.oneDay)))
367
- const dateEl = document.getElementById(`${d.getTime()}_date`)
368
- if (dateEl) {
369
- dateEl.classList.add('selected')
370
- if (d.getTime() === this.selectedRangeDates[0].getTime()) {
371
- dateEl.classList.add('first')
434
+ if (this.customRangeSelected === true) {
435
+ let diff
436
+ if (this.options.mode === 'date') {
437
+ diff = Math.floor((this.selectedRangeDates[this.selectedRangeDates.length - 1].getTime() - this.selectedRangeDates[0].getTime()) / this.oneDay)
438
+ if (this.selectedRangeDates[0].getMonth() !== this.selectedRangeDates[this.selectedRangeDates.length - 1].getMonth()) {
439
+ diff += 1
440
+ }
441
+ }
442
+ else if (this.options.mode === 'year') {
443
+ diff = this.selectedRangeDates[this.selectedRangeDates.length - 1] - this.selectedRangeDates[0]
444
+ if (this.selectedRangeDates[this.selectedRangeDates.length - 1] !== this.selectedRangeDates[0]) {
445
+ // diff += 1
446
+ }
447
+ }
448
+ for (let i = 0; i < diff + 1; i++) {
449
+ let d
450
+ let rangeStart
451
+ let rangeEnd
452
+ if (this.options.mode === 'date') {
453
+ d = this.floorDate(new Date(this.selectedRangeDates[0].getTime() + (i * this.oneDay)))
454
+ d = d.getTime()
455
+ rangeStart = this.selectedRangeDates[0].getTime()
456
+ rangeEnd = this.selectedRangeDates[this.selectedRangeDates.length - 1].getTime()
457
+ }
458
+ else if (this.options.mode === 'year') {
459
+ d = this.selectedRangeDates[0] + i
460
+ rangeStart = this.selectedRangeDates[0]
461
+ rangeEnd = this.selectedRangeDates[this.selectedRangeDates.length - 1]
462
+ }
463
+ let dateEl
464
+ if (this.options.mode === 'date') {
465
+ dateEl = document.getElementById(`${d.getTime()}_date`)
372
466
  }
373
- if (d.getTime() === this.selectedRangeDates[this.selectedRangeDates.length - 1].getTime()) {
374
- dateEl.classList.add('last')
467
+ else if (this.options.mode === 'year') {
468
+ dateEl = document.getElementById(`${d}_year`)
469
+ }
470
+ if (dateEl) {
471
+ dateEl.classList.add('selected')
472
+ if (d === rangeStart) {
473
+ dateEl.classList.add(`${this.options.sortDirection === 'desc' ? 'last' : 'first'}`)
474
+ }
475
+ if (d === rangeEnd) {
476
+ dateEl.classList.add(`${this.options.sortDirection === 'desc' ? 'first' : 'last'}`)
477
+ }
375
478
  }
376
479
  }
377
480
  }
481
+ else {
482
+ this.currentselection.forEach(d => {
483
+ let dateEl
484
+ if (this.options.mode === 'date') {
485
+ dateEl = document.getElementById(`${d}_date`)
486
+ }
487
+ else if (this.options.mode === 'year') {
488
+ dateEl = document.getElementById(`${d}_year`)
489
+ }
490
+ dateEl.classList.add('selected')
491
+ dateEl.classList.add('first')
492
+ dateEl.classList.add('last')
493
+ })
494
+ }
378
495
  }
379
496
  open (options, override = false) {
380
497
  const maskEl = document.getElementById(`${this.elementId}_mask`)
@@ -383,6 +500,8 @@ class WebsyDatePicker {
383
500
  contentEl.classList.add('active')
384
501
  this.priorSelectedDates = [...this.selectedRangeDates]
385
502
  this.priorSelectedRange = this.selectedRange
503
+ this.priorselection = [...this.currentselection]
504
+ this.priorCustomRangeSelected = this.customRangeSelected
386
505
  this.scrollRangeIntoView()
387
506
  }
388
507
  render (disabledDates) {
@@ -403,87 +522,154 @@ class WebsyDatePicker {
403
522
  renderDates (disabledDates) {
404
523
  let disabled = []
405
524
  this.validDates = []
525
+ this.validYears = []
406
526
  if (disabledDates) {
407
- disabled = disabledDates.map(d => d.getTime())
527
+ disabled = disabledDates.map(d => {
528
+ if (this.options.mode === 'date') {
529
+ return d.getTime()
530
+ }
531
+ else if (this.options.mode === 'year') {
532
+ return d
533
+ }
534
+ return d.getTime()
535
+ })
408
536
  }
409
537
  // first disabled all of the ranges
410
- this.options.ranges.forEach(r => (r.disabled = true))
411
- let daysDiff = Math.ceil((this.options.maxAllowedDate.getTime() - this.options.minAllowedDate.getTime()) / this.oneDay) + 1
538
+ this.options.ranges[this.options.mode].forEach(r => (r.disabled = true))
539
+ let diff
540
+ if (this.options.mode === 'date') {
541
+ diff = Math.ceil((this.options.maxAllowedDate.getTime() - this.options.minAllowedDate.getTime()) / this.oneDay) + 1
542
+ }
543
+ else if (this.options.mode === 'year') {
544
+ diff = (this.options.maxAllowedYear - this.options.minAllowedYear) + 1
545
+ }
412
546
  let months = {}
413
- for (let i = 0; i < daysDiff; i++) {
414
- let d = this.floorDate(new Date(this.options.minAllowedDate.getTime() + (i * this.oneDay)))
415
- let monthYear = `${this.options.monthMap[d.getMonth()]} ${d.getFullYear()}`
416
- if (!months[monthYear]) {
417
- months[monthYear] = []
418
- }
419
- if (disabled.indexOf(d.getTime()) === -1) {
420
- this.validDates.push(d.getTime())
547
+ let yearList = []
548
+ for (let i = 0; i < diff; i++) {
549
+ if (this.options.mode === 'date') {
550
+ let d = this.floorDate(new Date(this.options.minAllowedDate.getTime() + (i * this.oneDay)))
551
+ let monthYear = `${this.options.monthMap[d.getMonth()]} ${d.getFullYear()}`
552
+ if (!months[monthYear]) {
553
+ months[monthYear] = []
554
+ }
555
+ if (disabled.indexOf(d.getTime()) === -1) {
556
+ this.validDates.push(d.getTime())
557
+ }
558
+ months[monthYear].push({date: d, dayOfMonth: d.getDate(), dayOfWeek: d.getDay(), id: d.getTime(), disabled: disabled.indexOf(d.getTime()) !== -1})
421
559
  }
422
- months[monthYear].push({date: d, dayOfMonth: d.getDate(), dayOfWeek: d.getDay(), id: d.getTime(), disabled: disabled.indexOf(d.getTime()) !== -1})
560
+ else if (this.options.mode === 'year') {
561
+ let d = this.options.minAllowedYear + i
562
+ yearList.push({year: d, id: d, disabled: disabled.indexOf(d) !== -1})
563
+ if (disabled.indexOf(d) === -1) {
564
+ this.validYears.push(d)
565
+ }
566
+ }
423
567
  }
424
568
  // check each range to see if it can be enabled
425
- for (let i = 0; i < this.options.ranges.length; i++) {
426
- const r = this.options.ranges[i]
427
- // check the first date
428
- if (this.validDates.indexOf(r.range[0].getTime()) !== -1) {
429
- r.disabled = false
430
- }
431
- else if (r.range[1]) {
432
- // check the last date
433
- if (this.validDates.indexOf(r.range[1].getTime()) !== -1) {
569
+ for (let i = 0; i < this.options.ranges[this.options.mode].length; i++) {
570
+ const r = this.options.ranges[this.options.mode][i]
571
+ if (this.options.mode === 'date') {
572
+ // check the first date
573
+ if (this.validDates.indexOf(r.range[0].getTime()) !== -1) {
574
+ r.disabled = false
575
+ }
576
+ else if (r.range[1]) {
577
+ // check the last date
578
+ if (this.validDates.indexOf(r.range[1].getTime()) !== -1) {
579
+ r.disabled = false
580
+ }
581
+ else {
582
+ // check the full range until a match is found
583
+ for (let i = r.range[0].getTime(); i <= r.range[1].getTime(); i += this.oneDay) {
584
+ let testDate = this.floorDate(new Date(i))
585
+ if (this.validDates.indexOf(testDate.getTime()) !== -1) {
586
+ r.disabled = false
587
+ break
588
+ }
589
+ }
590
+ }
591
+ }
592
+ }
593
+ else if (this.options.mode === 'year') {
594
+ if (this.validYears.indexOf(r.range[0]) !== -1) {
434
595
  r.disabled = false
435
596
  }
436
- else {
437
- // check the full range until a match is found
438
- for (let i = r.range[0].getTime(); i <= r.range[1].getTime(); i += this.oneDay) {
439
- let testDate = this.floorDate(new Date(i))
440
- if (this.validDates.indexOf(testDate.getTime()) !== -1) {
441
- r.disabled = false
442
- break
443
- }
597
+ else if (r.range[1]) {
598
+ if (this.validYears.indexOf(r.range[1]) !== -1) {
599
+ r.disabled = false
600
+ }
601
+ else {
602
+ // check the full range until a match is found
603
+ for (let i = r.range[0]; i <= r.range[1]; i++) {
604
+ if (this.validYears.indexOf(r.range[0] + i) !== -1) {
605
+ r.disabled = false
606
+ break
607
+ }
608
+ }
444
609
  }
445
- }
446
- }
610
+ }
611
+ }
447
612
  }
448
613
  let html = ''
449
- html += `
450
- <ul class='websy-dp-days-header'>
451
- `
452
- html += this.options.daysOfWeek.map(d => `<li>${d}</li>`).join('')
453
- html += `
454
- </ul>
455
- <div id='${this.elementId}_dateList' class='websy-dp-date-list'>
456
- `
457
- for (let key in months) {
614
+ if (this.options.mode === 'date') {
458
615
  html += `
459
- <div class='websy-dp-month-container'>
460
- <span id='${key.replace(/\s/g, '_')}'>${key}</span>
461
- <ul>
616
+ <ul class='websy-dp-days-header'>
462
617
  `
463
- if (months[key][0].dayOfWeek > 0) {
464
- let paddedDays = []
465
- for (let i = 0; i < months[key][0].dayOfWeek; i++) {
466
- paddedDays.push(`<li>&nbsp;</li>`)
467
- }
468
- html += paddedDays.join('')
469
- }
470
- html += months[key].map(d => `<li id='${d.id}_date' class='websy-dp-date ${d.disabled === true ? 'websy-disabled-date' : ''}'>${d.dayOfMonth}</li>`).join('')
618
+ html += this.options.daysOfWeek.map(d => `<li>${d}</li>`).join('')
471
619
  html += `
472
- </ul>
473
- </div>
620
+ </ul>
621
+ <div id='${this.elementId}_dateList' class='websy-dp-date-list'>
474
622
  `
475
- }
476
- html += '</div>'
623
+ for (let key in months) {
624
+ html += `
625
+ <div class='websy-dp-month-container'>
626
+ <span id='${key.replace(/\s/g, '_')}'>${key}</span>
627
+ <ul>
628
+ `
629
+ if (months[key][0].dayOfWeek > 0) {
630
+ let paddedDays = []
631
+ for (let i = 0; i < months[key][0].dayOfWeek; i++) {
632
+ paddedDays.push(`<li>&nbsp;</li>`)
633
+ }
634
+ html += paddedDays.join('')
635
+ }
636
+ html += months[key].map(d => `<li id='${d.id}_date' class='websy-dp-date ${d.disabled === true ? 'websy-disabled-date' : ''}'>${d.dayOfMonth}</li>`).join('')
637
+ html += `
638
+ </ul>
639
+ </div>
640
+ `
641
+ }
642
+ html += '</div>'
643
+ }
644
+ else if (this.options.mode === 'year') {
645
+ if (this.options.sortDirection === 'desc') {
646
+ yearList.reverse()
647
+ }
648
+ html += `<div id='${this.elementId}_dateList' class='websy-dp-date-list'><ul>`
649
+ 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('')
650
+ html += `</ul></div>`
651
+ }
477
652
  return html
478
653
  }
479
654
  renderRanges () {
480
- return this.options.ranges.map((r, i) => `
655
+ return this.options.ranges[this.options.mode].map((r, i) => `
481
656
  <li data-index='${i}' class='websy-date-picker-range ${i === this.selectedRange ? 'active' : ''} ${r.disabled === true ? 'websy-disabled-range' : ''}'>${r.label}</li>
482
- `).join('')
657
+ `).join('') + `<li data-index='-1' class='websy-date-picker-range ${this.selectedRange === -1 ? 'active' : ''}'>Custom</li>`
483
658
  }
484
659
  scrollRangeIntoView () {
485
660
  if (this.selectedRangeDates[0]) {
486
- const el = document.getElementById(`${this.selectedRangeDates[0].getTime()}_date`)
661
+ let el
662
+ if (this.options.mode === 'date') {
663
+ el = document.getElementById(`${this.selectedRangeDates[0].getTime()}_date`)
664
+ }
665
+ else if (this.options.mode === 'year') {
666
+ if (this.options.sortDirection === 'desc') {
667
+ el = document.getElementById(`${this.selectedRangeDates[this.selectedRangeDates.length - 1]}_year`)
668
+ }
669
+ else {
670
+ el = document.getElementById(`${this.selectedRangeDates[0]}_year`)
671
+ }
672
+ }
487
673
  const parentEl = document.getElementById(`${this.elementId}_dateList`)
488
674
  if (el && parentEl) {
489
675
  parentEl.scrollTo(0, el.offsetTop)
@@ -495,23 +681,38 @@ class WebsyDatePicker {
495
681
  this.currentselection.push(timestamp)
496
682
  }
497
683
  else {
498
- if (timestamp > this.currentselection[0]) {
499
- this.currentselection.push(timestamp)
684
+ if (this.dragging === true) {
685
+ this.currentselection = [this.mouseDownId]
686
+ if (timestamp > this.currentselection[0]) {
687
+ this.currentselection.push(timestamp)
688
+ }
689
+ else {
690
+ this.currentselection.splice(0, 0, timestamp)
691
+ }
692
+ this.customRangeSelected = true
500
693
  }
501
694
  else {
502
- this.currentselection.splice(0, 0, timestamp)
503
- }
695
+ this.currentselection.push(timestamp)
696
+ this.currentselection.sort((a, b) => a - b)
697
+ this.customRangeSelected = false
698
+ }
504
699
  }
505
- this.selectedRangeDates = [new Date(this.currentselection[0]), new Date(this.currentselection[1] || this.currentselection[0])]
506
- if (this.currentselection.length === 2) {
507
- this.currentselection = []
700
+ if (this.options.mode === 'date') {
701
+ this.selectedRangeDates = [new Date(this.currentselection[0]), new Date(this.currentselection[1] || this.currentselection[0])]
508
702
  }
703
+ else if (this.options.mode === 'year') {
704
+ this.selectedRangeDates = [this.currentselection[0], this.currentselection[1] || this.currentselection[0]]
705
+ }
706
+ // if (this.currentselection.length === 2) {
707
+ // this.currentselection = []
708
+ // }
509
709
  this.selectedRange = -1
510
710
  this.highlightRange()
511
711
  }
512
712
  selectRange (index) {
513
- if (this.options.ranges[index]) {
514
- this.selectedRangeDates = [...this.options.ranges[index].range]
713
+ if (this.options.ranges[this.options.mode][index]) {
714
+ this.selectedRangeDates = [...this.options.ranges[this.options.mode][index].range]
715
+ this.currentselection = [...this.options.ranges[this.options.mode][index].range]
515
716
  this.selectedRange = +index
516
717
  this.highlightRange()
517
718
  this.close(true)
@@ -520,28 +721,60 @@ class WebsyDatePicker {
520
721
  selectCustomRange (range) {
521
722
  this.selectedRange = -1
522
723
  this.selectedRangeDates = range
724
+ // check if the custom range matches a configured range
725
+ for (let i = 0; i < this.options.ranges[this.options.mode].length; i++) {
726
+ if (this.options.ranges[this.options.mode][i].range.length === 1) {
727
+ if (this.options.ranges[this.options.mode][i].range[0] === range[0]) {
728
+ this.selectedRange = i
729
+ break
730
+ }
731
+ }
732
+ else if (this.options.ranges[this.options.mode][i].range.length === 2) {
733
+ if (this.options.ranges[this.options.mode][i].range[0] === range[0] && this.options.ranges[this.options.mode][i].range[1] === range[1]) {
734
+ this.selectedRange = i
735
+ break
736
+ }
737
+ }
738
+ }
523
739
  this.highlightRange()
524
740
  this.updateRange()
525
741
  }
526
742
  setDateBounds (range) {
527
- if (this.options.ranges[0].label === 'All Dates') {
528
- this.options.ranges[0].range = [range[0], range[1] || range[0]]
743
+ if (['All Dates', 'All Years'].indexOf(this.options.ranges[this.options.mode][0].label) !== -1) {
744
+ this.options.ranges[this.options.mode][0].range = [range[0], range[1] || range[0]]
529
745
  }
530
- this.options.minAllowedDate = range[0]
531
- this.options.maxAllowedDate = range[1] || range[0]
746
+ if (this.options.mode === 'date') {
747
+ this.options.minAllowedDate = range[0]
748
+ this.options.maxAllowedDate = range[1] || range[0]
749
+ }
750
+ else if (this.options.mode === 'year') {
751
+ this.options.minAllowedYear = range[0]
752
+ this.options.maxAllowedYear = range[1] || range[0]
753
+ }
532
754
  }
533
755
  updateRange () {
534
756
  let range
535
757
  if (this.selectedRange === -1) {
536
- let start = this.selectedRangeDates[0].toLocaleDateString()
758
+ const list = (this.currentselection.length > 0 ? this.currentselection : this.selectedRangeDates).map(d => {
759
+ if (this.options.mode === 'date') {
760
+ return d.toLocaleDateString()
761
+ }
762
+ else if (this.options.mode === 'year') {
763
+ return d
764
+ }
765
+ })
766
+ let start = list[0]
537
767
  let end = ''
538
- if (this.selectedRangeDates[1] && (this.selectedRangeDates[0].getTime() !== this.selectedRangeDates[1].getTime())) {
539
- end = ` - ${this.selectedRangeDates[1].toLocaleDateString()}`
540
- }
541
- range = { label: `${start}${end}` }
768
+ if (this.customRangeSelected === true) {
769
+ end = ` - ${list[list.length - 1]}`
770
+ }
771
+ else {
772
+ start = `${list.length} selected`
773
+ }
774
+ range = { label: `${start}${end}` }
542
775
  }
543
776
  else {
544
- range = this.options.ranges[this.selectedRange]
777
+ range = this.options.ranges[this.options.mode][this.selectedRange]
545
778
  }
546
779
  const el = document.getElementById(this.elementId)
547
780
  const labelEl = document.getElementById(`${this.elementId}_selectedRange`)
@@ -591,7 +824,45 @@ class WebsyDropdown {
591
824
  el.addEventListener('click', this.handleClick.bind(this))
592
825
  el.addEventListener('keyup', this.handleKeyUp.bind(this))
593
826
  el.addEventListener('mouseout', this.handleMouseOut.bind(this))
594
- el.addEventListener('mousemove', this.handleMouseMove.bind(this))
827
+ el.addEventListener('mousemove', this.handleMouseMove.bind(this))
828
+ const headerLabel = this.selectedItems.map(s => this.options.items[s].label || this.options.items[s].value).join(this.options.multiValueDelimiter)
829
+ const headerValue = this.selectedItems.map(s => this.options.items[s].value || this.options.items[s].label).join(this.options.multiValueDelimiter)
830
+ let html = `
831
+ <div id='${this.elementId}_container' class='websy-dropdown-container ${this.options.disabled ? 'disabled' : ''} ${this.options.disableSearch !== true ? 'with-search' : ''} ${this.options.style}'>
832
+ <div id='${this.elementId}_header' class='websy-dropdown-header ${this.selectedItems.length === 1 ? 'one-selected' : ''} ${this.options.allowClear === true ? 'allow-clear' : ''}'>
833
+ <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>
834
+ <span id='${this.elementId}_headerLabel' class='websy-dropdown-header-label'>${this.options.label}</span>
835
+ <span data-info='${headerLabel}' class='websy-dropdown-header-value' id='${this.elementId}_selectedItems'>${headerLabel}</span>
836
+ <input class='dropdown-input' id='${this.elementId}_input' name='${this.options.field || this.options.label}' value='${headerValue}'>
837
+ <svg class='arrow' xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M23.677 18.52c.914 1.523-.183 3.472-1.967 3.472h-19.414c-1.784 0-2.881-1.949-1.967-3.472l9.709-16.18c.891-1.483 3.041-1.48 3.93 0l9.709 16.18z"/></svg>
838
+ `
839
+ if (this.options.allowClear === true) {
840
+ html += `
841
+ <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>
842
+ `
843
+ }
844
+ html += `
845
+ </div>
846
+ <div id='${this.elementId}_mask' class='websy-dropdown-mask'></div>
847
+ <div id='${this.elementId}_content' class='websy-dropdown-content'>
848
+ `
849
+ if (this.options.disableSearch !== true) {
850
+ html += `
851
+ <input id='${this.elementId}_search' class='websy-dropdown-search' placeholder='${this.options.searchPlaceholder || 'Search'}'>
852
+ `
853
+ }
854
+ html += `
855
+ <div id='${this.elementId}_itemsContainer' class='websy-dropdown-items'>
856
+ <ul id='${this.elementId}_items'>
857
+ </ul>
858
+ </div><!--
859
+ --><div class='websy-dropdown-custom'></div>
860
+ </div>
861
+ </div>
862
+ `
863
+ el.innerHTML = html
864
+ const scrollEl = document.getElementById(`${this.elementId}_itemsContainer`)
865
+ scrollEl.addEventListener('scroll', this.handleScroll.bind(this))
595
866
  this.render()
596
867
  }
597
868
  else {
@@ -616,6 +887,9 @@ class WebsyDropdown {
616
887
  }
617
888
  get data () {
618
889
  return this.options.items
890
+ }
891
+ appendRows () {
892
+
619
893
  }
620
894
  clearSelected () {
621
895
  this.selectedItems = []
@@ -655,6 +929,10 @@ class WebsyDropdown {
655
929
  else if (event.target.classList.contains('clear')) {
656
930
  this.clearSelected()
657
931
  }
932
+ else if (event.target.classList.contains('search')) {
933
+ const el = document.getElementById(`${this.elementId}_container`)
934
+ el.classList.toggle('search-open')
935
+ }
658
936
  }
659
937
  handleKeyUp (event) {
660
938
  if (event.target.classList.contains('websy-dropdown-search')) {
@@ -724,6 +1002,13 @@ class WebsyDropdown {
724
1002
  clearTimeout(this.tooltipTimeoutFn)
725
1003
  }
726
1004
  }
1005
+ handleScroll (event) {
1006
+ if (event.target.classList.contains('websy-dropdown-items')) {
1007
+ if (this.options.onScroll) {
1008
+ this.options.onScroll(event)
1009
+ }
1010
+ }
1011
+ }
727
1012
  open (options, override = false) {
728
1013
  const maskEl = document.getElementById(`${this.elementId}_mask`)
729
1014
  const contentEl = document.getElementById(`${this.elementId}_content`)
@@ -744,42 +1029,42 @@ class WebsyDropdown {
744
1029
  console.log('No element Id provided for Websy Dropdown')
745
1030
  return
746
1031
  }
747
- const el = document.getElementById(this.elementId)
748
- const headerLabel = this.selectedItems.map(s => this.options.items[s].label || this.options.items[s].value).join(this.options.multiValueDelimiter)
749
- const headerValue = this.selectedItems.map(s => this.options.items[s].value || this.options.items[s].label).join(this.options.multiValueDelimiter)
750
- let html = `
751
- <div class='websy-dropdown-container ${this.options.disabled ? 'disabled' : ''} ${this.options.disableSearch !== true ? 'with-search' : ''}'>
752
- <div id='${this.elementId}_header' class='websy-dropdown-header ${this.selectedItems.length === 1 ? 'one-selected' : ''} ${this.options.allowClear === true ? 'allow-clear' : ''}'>
753
- <span id='${this.elementId}_headerLabel' class='websy-dropdown-header-label'>${this.options.label}</span>
754
- <span data-info='${headerLabel}' class='websy-dropdown-header-value' id='${this.elementId}_selectedItems'>${headerLabel}</span>
755
- <input class='dropdown-input' id='${this.elementId}_input' name='${this.options.field || this.options.label}' value='${headerValue}'>
756
- <svg class='arrow' xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M23.677 18.52c.914 1.523-.183 3.472-1.967 3.472h-19.414c-1.784 0-2.881-1.949-1.967-3.472l9.709-16.18c.891-1.483 3.041-1.48 3.93 0l9.709 16.18z"/></svg>
757
- `
758
- if (this.options.allowClear === true) {
759
- html += `
760
- <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>
761
- `
762
- }
763
- html += `
764
- </div>
765
- <div id='${this.elementId}_mask' class='websy-dropdown-mask'></div>
766
- <div id='${this.elementId}_content' class='websy-dropdown-content'>
767
- `
768
- if (this.options.disableSearch !== true) {
769
- html += `
770
- <input id='${this.elementId}_search' class='websy-dropdown-search' placeholder='${this.options.searchPlaceholder || 'Search'}'>
771
- `
772
- }
773
- html += `
774
- <div class='websy-dropdown-items'>
775
- <ul id='${this.elementId}_items'>
776
- </ul>
777
- </div><!--
778
- --><div class='websy-dropdown-custom'></div>
779
- </div>
780
- </div>
781
- `
782
- el.innerHTML = html
1032
+ // const el = document.getElementById(this.elementId)
1033
+ // const headerLabel = this.selectedItems.map(s => this.options.items[s].label || this.options.items[s].value).join(this.options.multiValueDelimiter)
1034
+ // const headerValue = this.selectedItems.map(s => this.options.items[s].value || this.options.items[s].label).join(this.options.multiValueDelimiter)
1035
+ // let html = `
1036
+ // <div class='websy-dropdown-container ${this.options.disabled ? 'disabled' : ''} ${this.options.disableSearch !== true ? 'with-search' : ''}'>
1037
+ // <div id='${this.elementId}_header' class='websy-dropdown-header ${this.selectedItems.length === 1 ? 'one-selected' : ''} ${this.options.allowClear === true ? 'allow-clear' : ''}'>
1038
+ // <span id='${this.elementId}_headerLabel' class='websy-dropdown-header-label'>${this.options.label}</span>
1039
+ // <span data-info='${headerLabel}' class='websy-dropdown-header-value' id='${this.elementId}_selectedItems'>${headerLabel}</span>
1040
+ // <input class='dropdown-input' id='${this.elementId}_input' name='${this.options.field || this.options.label}' value='${headerValue}'>
1041
+ // <svg class='arrow' xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M23.677 18.52c.914 1.523-.183 3.472-1.967 3.472h-19.414c-1.784 0-2.881-1.949-1.967-3.472l9.709-16.18c.891-1.483 3.041-1.48 3.93 0l9.709 16.18z"/></svg>
1042
+ // `
1043
+ // if (this.options.allowClear === true) {
1044
+ // html += `
1045
+ // <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>
1046
+ // `
1047
+ // }
1048
+ // html += `
1049
+ // </div>
1050
+ // <div id='${this.elementId}_mask' class='websy-dropdown-mask'></div>
1051
+ // <div id='${this.elementId}_content' class='websy-dropdown-content'>
1052
+ // `
1053
+ // if (this.options.disableSearch !== true) {
1054
+ // html += `
1055
+ // <input id='${this.elementId}_search' class='websy-dropdown-search' placeholder='${this.options.searchPlaceholder || 'Search'}'>
1056
+ // `
1057
+ // }
1058
+ // html += `
1059
+ // <div class='websy-dropdown-items'>
1060
+ // <ul id='${this.elementId}_items'>
1061
+ // </ul>
1062
+ // </div><!--
1063
+ // --><div class='websy-dropdown-custom'></div>
1064
+ // </div>
1065
+ // </div>
1066
+ // `
1067
+ // el.innerHTML = html
783
1068
  this.renderItems()
784
1069
  }
785
1070
  renderItems () {
@@ -829,9 +1114,11 @@ class WebsyDropdown {
829
1114
  }
830
1115
  if (labelEl) {
831
1116
  if (this.selectedItems.length === 1) {
832
- labelEl.innerHTML = item.label
833
- labelEl.setAttribute('data-info', item.label)
834
- inputEl.value = item.value
1117
+ if (item) {
1118
+ labelEl.innerHTML = item.label
1119
+ labelEl.setAttribute('data-info', item.label)
1120
+ inputEl.value = item.value
1121
+ }
835
1122
  }
836
1123
  else if (this.selectedItems.length > 1) {
837
1124
  if (this.options.showCompleteSelectedList === true) {
@@ -902,9 +1189,9 @@ class WebsyForm {
902
1189
  this.elementId = elementId
903
1190
  const el = document.getElementById(elementId)
904
1191
  if (el) {
905
- if (this.options.classes) {
906
- this.options.classes.forEach(c => el.classList.add(c))
907
- }
1192
+ // if (this.options.classes) {
1193
+ // this.options.classes.forEach(c => el.classList.add(c))
1194
+ // }
908
1195
  el.addEventListener('click', this.handleClick.bind(this))
909
1196
  el.addEventListener('keyup', this.handleKeyUp.bind(this))
910
1197
  el.addEventListener('keydown', this.handleKeyDown.bind(this))
@@ -992,7 +1279,7 @@ class WebsyForm {
992
1279
  else {
993
1280
  components.forEach(c => {
994
1281
  if (typeof WebsyDesigns[c.component] !== 'undefined') {
995
- const comp = new WebsyDesigns[c.component](`${this.elementId}_input_${c.field}_component`, c.options)
1282
+ c.instance = new WebsyDesigns[c.component](`${this.elementId}_input_${c.field}_component`, c.options)
996
1283
  }
997
1284
  else {
998
1285
  // some user feedback here
@@ -1014,13 +1301,13 @@ class WebsyForm {
1014
1301
  let componentsToProcess = []
1015
1302
  if (el) {
1016
1303
  let html = `
1017
- <form id="${this.elementId}Form">
1304
+ <form id="${this.elementId}Form" class="${this.options.classes || ''}">
1018
1305
  `
1019
1306
  this.options.fields.forEach((f, i) => {
1020
1307
  if (f.component) {
1021
1308
  componentsToProcess.push(f)
1022
1309
  html += `
1023
- ${i > 0 ? '-->' : ''}<div class='${f.classes}'>
1310
+ ${i > 0 ? '-->' : ''}<div class='${f.classes || ''}'>
1024
1311
  ${f.label ? `<label for="${f.field}">${f.label}</label>` : ''}
1025
1312
  <div id='${this.elementId}_input_${f.field}_component' class='form-component'></div>
1026
1313
  </div><!--
@@ -1028,7 +1315,7 @@ class WebsyForm {
1028
1315
  }
1029
1316
  else if (f.type === 'longtext') {
1030
1317
  html += `
1031
- ${i > 0 ? '-->' : ''}<div class='${f.classes}'>
1318
+ ${i > 0 ? '-->' : ''}<div class='${f.classes || ''}'>
1032
1319
  ${f.label ? `<label for="${f.field}">${f.label}</label>` : ''}
1033
1320
  <textarea
1034
1321
  id="${this.elementId}_input_${f.field}"
@@ -1042,7 +1329,7 @@ class WebsyForm {
1042
1329
  }
1043
1330
  else {
1044
1331
  html += `
1045
- ${i > 0 ? '-->' : ''}<div class='${f.classes}'>
1332
+ ${i > 0 ? '-->' : ''}<div class='${f.classes || ''}'>
1046
1333
  ${f.label ? `<label for="${f.field}">${f.label}</label>` : ''}
1047
1334
  <input
1048
1335
  id="${this.elementId}_input_${f.field}"
@@ -1052,6 +1339,7 @@ class WebsyForm {
1052
1339
  name="${f.field}"
1053
1340
  placeholder="${f.placeholder || ''}"
1054
1341
  value="${f.value || ''}"
1342
+ valueAsDate="${f.type === 'date' ? f.value : ''}"
1055
1343
  oninvalidx="this.setCustomValidity('${f.invalidMessage || 'Please fill in this field.'}')"
1056
1344
  />
1057
1345
  </div><!--
@@ -1059,11 +1347,11 @@ class WebsyForm {
1059
1347
  }
1060
1348
  })
1061
1349
  html += `
1062
- --><button class="websy-btn submit ${this.options.submit.classes}">${this.options.submit.text || 'Save'}</button>${this.options.cancel ? '<!--' : ''}
1350
+ --><button class="websy-btn submit ${this.options.submit.classes || ''}">${this.options.submit.text || 'Save'}</button>${this.options.cancel ? '<!--' : ''}
1063
1351
  `
1064
1352
  if (this.options.cancel) {
1065
1353
  html += `
1066
- --><button class="websy-btn cancel ${this.options.cancel.classes}">${this.options.cancel.text || 'Cancel'}</button>
1354
+ --><button class="websy-btn cancel ${this.options.cancel.classes || ''}">${this.options.cancel.text || 'Cancel'}</button>
1067
1355
  `
1068
1356
  }
1069
1357
  html += `
@@ -1284,9 +1572,6 @@ class WebsyNavigationMenu {
1284
1572
  html += this.renderBlock(this.options.items, 'main', 0)
1285
1573
  html += `</div>`
1286
1574
  el.innerHTML = html
1287
- if (this.options.navigator) {
1288
- this.options.navigator.registerElements(el)
1289
- }
1290
1575
  }
1291
1576
  }
1292
1577
  renderBlock (items, block, level = 0) {
@@ -1378,6 +1663,92 @@ class WebsyNavigationMenu {
1378
1663
  }
1379
1664
  }
1380
1665
 
1666
+ /* global WebsyDesigns */
1667
+ class Pager {
1668
+ constructor (elementId, options) {
1669
+ this.elementId = elementId
1670
+ const DEFAULTS = {
1671
+ pageSizePrefix: 'Show',
1672
+ pageSizeSuffix: 'rows',
1673
+ pageSizeOptions: [
1674
+ { label: '10', value: 10 },
1675
+ { label: '20', value: 20 },
1676
+ { label: '50', value: 50 },
1677
+ { label: '100', value: 100 }
1678
+ ],
1679
+ selectedPageSize: 20,
1680
+ pageLabel: 'Page',
1681
+ showPageSize: true,
1682
+ activePage: 0,
1683
+ pages: []
1684
+ }
1685
+ this.options = Object.assign({}, DEFAULTS, options)
1686
+ const el = document.getElementById(this.elementId)
1687
+ if (el) {
1688
+ let html = `
1689
+ <div class="websy-pager-container">
1690
+ `
1691
+ if (this.options.showPageSize === true) {
1692
+ html += `
1693
+ ${this.options.pageSizePrefix} <div id="${this.elementId}_pageSizeSelector" class="websy-page-selector"></div> ${this.options.pageSizeSuffix}
1694
+ `
1695
+ }
1696
+ html += `
1697
+ <ul id="${this.elementId}_pageList" class="websy-page-list"></ul>
1698
+ </div>
1699
+ `
1700
+ el.innerHTML = html
1701
+ el.addEventListener('click', this.handleClick.bind(this))
1702
+ if (this.options.showPageSize === true) {
1703
+ this.pageSizeSelector = new WebsyDesigns.Dropdown(`${this.elementId}_pageSizeSelector`, {
1704
+ selectedItems: [this.options.pageSizeOptions.indexOf(this.options.selectedPageSize)],
1705
+ items: this.pageSizeOptions.map(p => ({ label: p.toString(), value: p })),
1706
+ allowClear: false,
1707
+ disableSearch: true,
1708
+ onItemSelected: (selectedItem) => {
1709
+ if (this.options.onChangePageSize) {
1710
+ this.options.onChangePageSize(selectedItem.value)
1711
+ }
1712
+ }
1713
+ })
1714
+ }
1715
+ this.render()
1716
+ }
1717
+ }
1718
+ handleClick (event) {
1719
+ if (event.target.classList.contains('websy-page-num')) {
1720
+ const pageNum = +event.target.getAttribute('data-index')
1721
+ if (this.options.onSetPage) {
1722
+ this.options.onSetPage(this.options.pages[pageNum])
1723
+ }
1724
+ }
1725
+ }
1726
+ render () {
1727
+ const el = document.getElementById(`${this.elementId}_pageList`)
1728
+ if (el) {
1729
+ let pages = this.options.pages.map((item, index) => {
1730
+ return `<li data-index="${index}" class="websy-page-num ${(this.options.activePage === index) ? 'active' : ''}">${index + 1}</li>`
1731
+ })
1732
+ let startIndex = 0
1733
+ if (this.options.pages.length > 8) {
1734
+ startIndex = Math.max(0, this.options.activePage - 4)
1735
+ pages = pages.splice(startIndex, 10)
1736
+ if (startIndex > 0) {
1737
+ pages.splice(0, 0, `<li>${this.options.pageLabel}&nbsp;</li><li data-page="0" class="websy-page-num">First</li><li>...</li>`)
1738
+ }
1739
+ else {
1740
+ pages.splice(0, 0, `<li>${this.options.pageLabel}&nbsp;</li>`)
1741
+ }
1742
+ if (this.options.activePage < this.options.pages.length - 1) {
1743
+ pages.push('<li>...</li>')
1744
+ pages.push(`<li data-page="${this.options.pages.length - 1}" class="websy-page-num">Last</li>`)
1745
+ }
1746
+ }
1747
+ el.innerHTML = pages.join('')
1748
+ }
1749
+ }
1750
+ }
1751
+
1381
1752
  /* global WebsyDesigns Blob */
1382
1753
  class WebsyPDFButton {
1383
1754
  constructor (elementId, options) {
@@ -2853,6 +3224,9 @@ class WebsyTable {
2853
3224
  }
2854
3225
  if (c.backgroundColor) {
2855
3226
  style += `background-color: ${c.backgroundColor}; `
3227
+ if (!c.color) {
3228
+ style += `color: ${WebsyDesigns.Utils.getLightDark(c.backgroundColor)}; `
3229
+ }
2856
3230
  }
2857
3231
  if (c.color) {
2858
3232
  style += `color: ${c.color}; `
@@ -3145,34 +3519,562 @@ class WebsyTable {
3145
3519
  }
3146
3520
  }
3147
3521
 
3148
- /* global d3 include WebsyDesigns */
3149
- class WebsyChart {
3522
+ /* global WebsyDesigns */
3523
+ class WebsyTable2 {
3150
3524
  constructor (elementId, options) {
3151
3525
  const DEFAULTS = {
3152
- margin: {
3153
- top: 10,
3154
- left: 3,
3155
- bottom: 3,
3156
- right: 3,
3157
- axisBottom: 0,
3158
- axisLeft: 0,
3159
- axisRight: 0,
3160
- axisTop: 0,
3161
- legendBottom: 0,
3162
- legendLeft: 0,
3163
- legendRight: 0,
3164
- legendTop: 0
3165
- },
3166
- orientation: 'vertical',
3167
- colors: ['#5e4fa2', '#3288bd', '#66c2a5', '#abdda4', '#e6f598', '#fee08b', '#fdae61', '#f46d43', '#d53e4f', '#9e0142'],
3168
- transitionDuration: 650,
3169
- curveStyle: 'curveLinear',
3170
- lineWidth: 2,
3171
- forceZero: true,
3172
- fontSize: 14,
3173
- symbolSize: 20,
3174
- showTrackingLine: true,
3175
- showTooltip: true,
3526
+ pageSize: 20,
3527
+ paging: 'scroll',
3528
+ cellSize: 35,
3529
+ virtualScroll: false,
3530
+ leftColumns: 0
3531
+ }
3532
+ this.elementId = elementId
3533
+ this.options = Object.assign({}, DEFAULTS, options)
3534
+ this.rowCount = 0
3535
+ this.busy = false
3536
+ this.tooltipTimeoutFn = null
3537
+ this.data = []
3538
+ const el = document.getElementById(this.elementId)
3539
+ if (el) {
3540
+ let html = `
3541
+ <div id='${this.elementId}_tableContainer' class='websy-vis-table ${this.options.paging === 'pages' ? 'with-paging' : ''} ${this.options.virtualScroll === true ? 'with-virtual-scroll' : ''}'>
3542
+ <!--<div class="download-button">
3543
+ <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>
3544
+ </div>-->
3545
+ <table id="${this.elementId}_table">
3546
+ <thead id="${this.elementId}_head">
3547
+ </thead>
3548
+ <tbody id="${this.elementId}_body">
3549
+ </tbody>
3550
+ <tfoot id="${this.elementId}_foot">
3551
+ </tfoot>
3552
+ </table>
3553
+ <div id="${this.elementId}_errorContainer" class='websy-vis-error-container'>
3554
+ <div>
3555
+ <div id="${this.elementId}_errorTitle"></div>
3556
+ <div id="${this.elementId}_errorMessage"></div>
3557
+ </div>
3558
+ </div>
3559
+ <div id="${this.elementId}_vScrollContainer" class="websy-v-scroll-container">
3560
+ <div id="${this.elementId}_vScrollHandle" class="websy-scroll-handle websy-scroll-handle-y"></div>
3561
+ </div>
3562
+ <div id="${this.elementId}_hScrollContainer" class="websy-h-scroll-container">
3563
+ <div id="${this.elementId}_hScrollHandle" class="websy-scroll-handle websy-scroll-handle-x"></div>
3564
+ </div>
3565
+ <div id="${this.elementId}_dropdownContainer"></div>
3566
+ <div id="${this.elementId}_loadingContainer"></div>
3567
+ </div>
3568
+ `
3569
+ if (this.options.paging === 'pages') {
3570
+ html += `
3571
+ <div class="websy-table-paging-container">
3572
+ Show <div id="${this.elementId}_pageSizeSelector" class="websy-vis-page-selector"></div> rows
3573
+ <ul id="${this.elementId}_pageList" class="websy-vis-page-list"></ul>
3574
+ </div>
3575
+ `
3576
+ }
3577
+ let pageOptions = [10, 20, 50, 100, 200]
3578
+ el.innerHTML = html
3579
+ if (this.options.paging === 'pages') {
3580
+ this.pageSizeSelector = new WebsyDesigns.Dropdown(`${this.elementId}_pageSizeSelector`, {
3581
+ selectedItems: [pageOptions.indexOf(this.options.pageSize)],
3582
+ items: pageOptions.map(p => ({ label: p.toString(), value: p })),
3583
+ allowClear: false,
3584
+ disableSearch: true,
3585
+ onItemSelected: (selectedItem) => {
3586
+ if (this.options.onChangePageSize) {
3587
+ this.options.onChangePageSize(selectedItem.value)
3588
+ }
3589
+ }
3590
+ })
3591
+ }
3592
+ el.addEventListener('click', this.handleClick.bind(this))
3593
+ el.addEventListener('mouseout', this.handleMouseOut.bind(this))
3594
+ el.addEventListener('mousemove', this.handleMouseMove.bind(this))
3595
+ el.addEventListener('mousedown', this.handleMouseDown.bind(this))
3596
+ el.addEventListener('mouseup', this.handleMouseUp.bind(this))
3597
+ document.addEventListener('mouseup', this.handleGlobalMouseUp.bind(this))
3598
+ const scrollEl = document.getElementById(`${this.elementId}_tableContainer`)
3599
+ scrollEl.addEventListener('scroll', this.handleScroll.bind(this))
3600
+ this.loadingDialog = new WebsyDesigns.LoadingDialog(`${this.elementId}_loadingContainer`)
3601
+ this.render()
3602
+ }
3603
+ else {
3604
+ console.error(`No element found with ID ${this.elementId}`)
3605
+ }
3606
+ }
3607
+ appendRows (data) {
3608
+ this.hideError()
3609
+ const bodyEl = document.getElementById(`${this.elementId}_body`)
3610
+ let bodyHTML = ''
3611
+ if (data) {
3612
+ bodyHTML += data.map((r, rowIndex) => {
3613
+ return '<tr>' + r.map((c, i) => {
3614
+ if (this.options.columns[i].show !== false) {
3615
+ let style = `height: ${this.options.cellSize}px; line-height: ${this.options.cellSize}px;`
3616
+ if (c.style) {
3617
+ style += c.style
3618
+ }
3619
+ if (this.options.columns[i].width) {
3620
+ style += `width: ${this.options.columns[i].width}; `
3621
+ }
3622
+ if (c.backgroundColor) {
3623
+ style += `background-color: ${c.backgroundColor}; `
3624
+ if (!c.color) {
3625
+ style += `color: ${WebsyDesigns.Utils.getLightDark(c.backgroundColor)}; `
3626
+ }
3627
+ }
3628
+ if (c.color) {
3629
+ style += `color: ${c.color}; `
3630
+ }
3631
+ if (this.options.columns[i].showAsLink === true && c.value.trim() !== '') {
3632
+ return `
3633
+ <td
3634
+ data-row-index='${this.rowCount + rowIndex}'
3635
+ data-col-index='${i}'
3636
+ class='${this.options.columns[i].classes || ''}'
3637
+ style='${style}'
3638
+ colspan='${c.colspan || 1}'
3639
+ rowspan='${c.rowspan || 1}'
3640
+ >
3641
+ <a href='${c.value}' target='${this.options.columns[i].openInNewTab === true ? '_blank' : '_self'}'>${c.displayText || this.options.columns[i].linkText || c.value}</a>
3642
+ </td>
3643
+ `
3644
+ }
3645
+ else if ((this.options.columns[i].showAsNavigatorLink === true || this.options.columns[i].showAsRouterLink === true) && c.value.trim() !== '') {
3646
+ return `
3647
+ <td
3648
+ data-view='${c.value}'
3649
+ data-row-index='${this.rowCount + rowIndex}'
3650
+ data-col-index='${i}'
3651
+ class='trigger-item ${this.options.columns[i].clickable === true ? 'clickable' : ''} ${this.options.columns[i].classes || ''}'
3652
+ style='${style}'
3653
+ colspan='${c.colspan || 1}'
3654
+ rowspan='${c.rowspan || 1}'
3655
+ >${c.displayText || this.options.columns[i].linkText || c.value}</td>
3656
+ `
3657
+ }
3658
+ else {
3659
+ let info = c.value
3660
+ if (this.options.columns[i].showAsImage === true) {
3661
+ c.value = `
3662
+ <img src='${c.value}'>
3663
+ `
3664
+ }
3665
+ return `
3666
+ <td
3667
+ data-info='${info}'
3668
+ data-row-index='${this.rowCount + rowIndex}'
3669
+ data-col-index='${i}'
3670
+ class='${this.options.columns[i].classes || ''}'
3671
+ style='${style}'
3672
+ colspan='${c.colspan || 1}'
3673
+ rowspan='${c.rowspan || 1}'
3674
+ >${c.value}</td>
3675
+ `
3676
+ }
3677
+ }
3678
+ }).join('') + '</tr>'
3679
+ }).join('')
3680
+ this.data = this.data.concat(data)
3681
+ this.rowCount = this.data.length
3682
+ }
3683
+ bodyEl.innerHTML += bodyHTML
3684
+ if (this.options.virtualScroll === true) {
3685
+ // get height of the thead
3686
+ if (this.options.paging !== 'pages') {
3687
+ const headEl = document.getElementById(`${this.elementId}_head`)
3688
+ const vScrollContainerEl = document.getElementById(`${this.elementId}_vScrollContainer`)
3689
+ vScrollContainerEl.style.top = `${headEl.clientHeight}px`
3690
+ }
3691
+ const hScrollContainerEl = document.getElementById(`${this.elementId}_hScrollContainer`)
3692
+ let left = 0
3693
+ const cells = bodyEl.querySelectorAll(`tr:first-of-type td`)
3694
+ for (let i = 0; i < this.options.leftColumns; i++) {
3695
+ left += cells[i].offsetWidth || cells[i].clientWidth
3696
+ }
3697
+ hScrollContainerEl.style.left = `${left}px`
3698
+ }
3699
+ }
3700
+ buildSearchIcon (columnIndex) {
3701
+ return `
3702
+ <div class="websy-table-search-icon" data-col-index="${columnIndex}">
3703
+ <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>
3704
+ </div>
3705
+ `
3706
+ }
3707
+ handleClick (event) {
3708
+ if (event.target.classList.contains('download-button')) {
3709
+ window.viewManager.dataExportController.exportData(this.options.model)
3710
+ }
3711
+ if (event.target.classList.contains('sortable-column')) {
3712
+ const colIndex = +event.target.getAttribute('data-index')
3713
+ const column = this.options.columns[colIndex]
3714
+ if (this.options.onSort) {
3715
+ this.options.onSort(event, column, colIndex)
3716
+ }
3717
+ else {
3718
+ this.internalSort(column, colIndex)
3719
+ }
3720
+ // const colIndex = +event.target.getAttribute('data-index')
3721
+ // const dimIndex = +event.target.getAttribute('data-dim-index')
3722
+ // const expIndex = +event.target.getAttribute('data-exp-index')
3723
+ // const reverse = event.target.getAttribute('data-reverse') === 'true'
3724
+ // const patchDefs = [{
3725
+ // qOp: 'replace',
3726
+ // qPath: '/qHyperCubeDef/qInterColumnSortOrder',
3727
+ // qValue: JSON.stringify([colIndex])
3728
+ // }]
3729
+ // patchDefs.push({
3730
+ // qOp: 'replace',
3731
+ // qPath: `/qHyperCubeDef/${dimIndex > -1 ? 'qDimensions' : 'qMeasures'}/${dimIndex > -1 ? dimIndex : expIndex}/qDef/qReverseSort`,
3732
+ // qValue: JSON.stringify(reverse)
3733
+ // })
3734
+ // this.options.model.applyPatches(patchDefs) // .then(() => this.render())
3735
+ }
3736
+ else if (event.target.classList.contains('websy-table-search-icon')) {
3737
+ // let field = event.target.getAttribute('data-field')
3738
+ // window.viewManager.views.global.objects[1].instance.show(field, { x: event.pageX, y: event.pageY }, () => {
3739
+ // event.target.classList.remove('active')
3740
+ // })
3741
+ const colIndex = +event.target.getAttribute('data-col-index')
3742
+ if (this.options.columns[colIndex].onSearch) {
3743
+ this.options.columns[colIndex].onSearch(event, this.options.columns[colIndex])
3744
+ }
3745
+ }
3746
+ else if (event.target.classList.contains('clickable')) {
3747
+ const colIndex = +event.target.getAttribute('data-col-index')
3748
+ const rowIndex = +event.target.getAttribute('data-row-index')
3749
+ if (this.options.onClick) {
3750
+ this.options.onClick(event, this.data[rowIndex][colIndex], this.data[rowIndex], this.options.columns[colIndex])
3751
+ }
3752
+ }
3753
+ else if (event.target.classList.contains('websy-page-num')) {
3754
+ const pageNum = +event.target.getAttribute('data-page')
3755
+ if (this.options.onSetPage) {
3756
+ this.options.onSetPage(pageNum)
3757
+ }
3758
+ }
3759
+ }
3760
+ handleMouseDown (event) {
3761
+ if (event.target.classList.contains('websy-scroll-handle')) {
3762
+ this.scrolling = true
3763
+ const el = document.getElementById(this.elementId)
3764
+ el.classList.add('scrolling')
3765
+ }
3766
+ if (event.target.classList.contains('websy-scroll-handle-x')) {
3767
+ const handleEl = document.getElementById(`${this.elementId}_hScrollHandle`)
3768
+ this.handleXStart = handleEl.offsetLeft
3769
+ this.scrollXStart = event.clientX
3770
+ this.scrollDirection = 'X'
3771
+ }
3772
+ }
3773
+ handleGlobalMouseUp (event) {
3774
+ this.scrolling = false
3775
+ const el = document.getElementById(this.elementId)
3776
+ el.classList.remove('scrolling')
3777
+ }
3778
+ handleMouseUp (event) {
3779
+ this.scrolling = false
3780
+ const el = document.getElementById(this.elementId)
3781
+ el.classList.remove('scrolling')
3782
+ }
3783
+ handleMouseMove (event) {
3784
+ if (this.tooltipTimeoutFn) {
3785
+ event.target.classList.remove('websy-delayed-info')
3786
+ clearTimeout(this.tooltipTimeoutFn)
3787
+ }
3788
+ if (event.target.tagName === 'TD') {
3789
+ this.tooltipTimeoutFn = setTimeout(() => {
3790
+ event.target.classList.add('websy-delayed-info')
3791
+ }, 500)
3792
+ }
3793
+ if (this.scrolling === true && this.options.virtualScroll === true) {
3794
+ const tableContainerEl = document.getElementById(`${this.elementId}_tableContainer`)
3795
+ if (this.scrollDirection === 'X') {
3796
+ const handleEl = document.getElementById(`${this.elementId}_hScrollHandle`)
3797
+ // console.log(this.handleXStart + handleEl.offsetWidth + (event.clientX - this.scrollXStart), this.columnParameters.scrollableWidth)
3798
+ let startPoint = 0
3799
+ if (this.handleXStart + (event.clientX - this.scrollXStart) < this.columnParameters.scrollableWidth - handleEl.offsetWidth) {
3800
+ handleEl.style.left = `${this.handleXStart + (event.clientX - this.scrollXStart)}px`
3801
+ startPoint = this.handleXStart + (event.clientX - this.scrollXStart)
3802
+ }
3803
+ else {
3804
+ startPoint = this.columnParameters.scrollableWidth - handleEl.offsetWidth
3805
+ }
3806
+ if (this.handleXStart + (event.clientX - this.scrollXStart) < 0) {
3807
+ handleEl.style.left = 0
3808
+ startPoint = 0
3809
+ }
3810
+ if (this.options.onScrollX) {
3811
+ this.options.onScrollX(startPoint)
3812
+ }
3813
+ }
3814
+ }
3815
+ }
3816
+ handleMouseOut (event) {
3817
+ if (this.tooltipTimeoutFn) {
3818
+ event.target.classList.remove('websy-delayed-info')
3819
+ clearTimeout(this.tooltipTimeoutFn)
3820
+ }
3821
+ }
3822
+ handleScroll (event) {
3823
+ if (this.options.onScroll && this.options.paging === 'scroll') {
3824
+ this.options.onScroll(event)
3825
+ }
3826
+ }
3827
+ hideError () {
3828
+ const el = document.getElementById(`${this.elementId}_tableContainer`)
3829
+ if (el) {
3830
+ el.classList.remove('has-error')
3831
+ }
3832
+ const tableEl = document.getElementById(`${this.elementId}_table`)
3833
+ tableEl.classList.remove('hidden')
3834
+ const containerEl = document.getElementById(`${this.elementId}_errorContainer`)
3835
+ if (containerEl) {
3836
+ containerEl.classList.remove('active')
3837
+ }
3838
+ }
3839
+ hideLoading () {
3840
+ this.loadingDialog.hide()
3841
+ }
3842
+ internalSort (column, colIndex) {
3843
+ this.options.columns.forEach((c, i) => {
3844
+ c.activeSort = i === colIndex
3845
+ })
3846
+ if (column.sortFunction) {
3847
+ this.data = column.sortFunction(this.data, column)
3848
+ }
3849
+ else {
3850
+ let sortProp = 'value'
3851
+ let sortOrder = column.sort === 'asc' ? 'desc' : 'asc'
3852
+ column.sort = sortOrder
3853
+ let sortType = column.sortType || 'alphanumeric'
3854
+ if (column.sortProp) {
3855
+ sortProp = column.sortProp
3856
+ }
3857
+ this.data.sort((a, b) => {
3858
+ switch (sortType) {
3859
+ case 'numeric':
3860
+ if (sortOrder === 'asc') {
3861
+ return a[colIndex][sortProp] - b[colIndex][sortProp]
3862
+ }
3863
+ else {
3864
+ return b[colIndex][sortProp] - a[colIndex][sortProp]
3865
+ }
3866
+ default:
3867
+ if (sortOrder === 'asc') {
3868
+ return a[colIndex][sortProp] > b[colIndex][sortProp] ? 1 : -1
3869
+ }
3870
+ else {
3871
+ return a[colIndex][sortProp] < b[colIndex][sortProp] ? 1 : -1
3872
+ }
3873
+ }
3874
+ })
3875
+ }
3876
+ this.render(this.data)
3877
+ }
3878
+ render (data) {
3879
+ if (!this.options.columns) {
3880
+ return
3881
+ }
3882
+ this.hideError()
3883
+ this.data = []
3884
+ this.rowCount = 0
3885
+ const bodyEl = document.getElementById(`${this.elementId}_body`)
3886
+ bodyEl.innerHTML = ''
3887
+ if (this.options.allowDownload === true) {
3888
+ // doesn't do anything yet
3889
+ const el = document.getElementById(this.elementId)
3890
+ if (el) {
3891
+ el.classList.add('allow-download')
3892
+ }
3893
+ else {
3894
+ el.classList.remove('allow-download')
3895
+ }
3896
+ }
3897
+ // let colGroupHTML = this.options.columns.map(c => `<col style="${c.width ? 'width: ' + c.width : ''}"></col>`)
3898
+ let headHTML = '<tr>' + this.options.columns.map((c, i) => {
3899
+ if (c.show !== false) {
3900
+ return `
3901
+ <th ${c.width ? 'style="width: ' + (c.width || 'auto') + ';"' : ''}>
3902
+ <div class ="tableHeader">
3903
+ <div class="leftSection">
3904
+ <div
3905
+ class="tableHeaderField ${['asc', 'desc'].indexOf(c.sort) !== -1 ? 'sortable-column' : ''}"
3906
+ data-index="${i}"
3907
+ data-sort="${c.sort}"
3908
+ >
3909
+ ${c.name}
3910
+ </div>
3911
+ </div>
3912
+ <div class="${c.activeSort ? c.sort + ' sortOrder' : ''}"></div>
3913
+ ${c.searchable === true ? this.buildSearchIcon(i) : ''}
3914
+ </div>
3915
+ </th>
3916
+ `
3917
+ }
3918
+ }).join('') + '</tr>'
3919
+ const headEl = document.getElementById(`${this.elementId}_head`)
3920
+ headEl.innerHTML = headHTML
3921
+ const dropdownEl = document.getElementById(`${this.elementId}_dropdownContainer`)
3922
+ if (dropdownEl.innerHTML === '') {
3923
+ let dropdownHTML = ``
3924
+ this.options.columns.forEach((c, i) => {
3925
+ if (c.searchable && c.searchField) {
3926
+ dropdownHTML += `
3927
+ <div id="${this.elementId}_columnSearch_${i}" class="websy-modal-dropdown"></div>
3928
+ `
3929
+ }
3930
+ })
3931
+ dropdownEl.innerHTML = dropdownHTML
3932
+ }
3933
+ // const colGroupEl = document.getElementById(`${this.elementId}_cols`)
3934
+ // colGroupEl.innerHTML = colGroupHTML
3935
+ // let footHTML = '<tr>' + this.options.columns.map((c, i) => {
3936
+ // if (c.show !== false) {
3937
+ // return `
3938
+ // <th></th>
3939
+ // `
3940
+ // }
3941
+ // }).join('') + '</tr>'
3942
+ // const footEl = document.getElementById(`${this.elementId}_foot`)
3943
+ // footEl.innerHTML = footHTML
3944
+ if (this.options.paging === 'pages') {
3945
+ const pagingEl = document.getElementById(`${this.elementId}_pageList`)
3946
+ if (pagingEl) {
3947
+ let pages = (new Array(this.options.pageCount)).fill('').map((item, index) => {
3948
+ return `<li data-page="${index}" class="websy-page-num ${(this.options.pageNum === index) ? 'active' : ''}">${index + 1}</li>`
3949
+ })
3950
+ let startIndex = 0
3951
+ if (this.options.pageCount > 8) {
3952
+ startIndex = Math.max(0, this.options.pageNum - 4)
3953
+ pages = pages.splice(startIndex, 10)
3954
+ if (startIndex > 0) {
3955
+ pages.splice(0, 0, `<li>Page&nbsp;</li><li data-page="0" class="websy-page-num">First</li><li>...</li>`)
3956
+ }
3957
+ else {
3958
+ pages.splice(0, 0, '<li>Page&nbsp;</li>')
3959
+ }
3960
+ if (this.options.pageNum < this.options.pageCount - 1) {
3961
+ pages.push('<li>...</li>')
3962
+ pages.push(`<li data-page="${this.options.pageCount - 1}" class="websy-page-num">Last</li>`)
3963
+ }
3964
+ }
3965
+ pagingEl.innerHTML = pages.join('')
3966
+ }
3967
+ }
3968
+ if (data) {
3969
+ this.appendRows(data)
3970
+ }
3971
+ }
3972
+ showError (options) {
3973
+ const el = document.getElementById(`${this.elementId}_tableContainer`)
3974
+ if (el) {
3975
+ el.classList.add('has-error')
3976
+ }
3977
+ const tableEl = document.getElementById(`${this.elementId}_table`)
3978
+ tableEl.classList.add('hidden')
3979
+ const containerEl = document.getElementById(`${this.elementId}_errorContainer`)
3980
+ if (containerEl) {
3981
+ containerEl.classList.add('active')
3982
+ }
3983
+ if (options.title) {
3984
+ const titleEl = document.getElementById(`${this.elementId}_errorTitle`)
3985
+ if (titleEl) {
3986
+ titleEl.innerHTML = options.title
3987
+ }
3988
+ }
3989
+ if (options.message) {
3990
+ const messageEl = document.getElementById(`${this.elementId}_errorMessage`)
3991
+ if (messageEl) {
3992
+ messageEl.innerHTML = options.message
3993
+ }
3994
+ }
3995
+ }
3996
+ setHorizontalScroll (options) {
3997
+ const el = document.getElementById(`${this.elementId}_hScrollHandle`)
3998
+ if (options.width) {
3999
+ el.style.width = `${options.width}px`
4000
+ }
4001
+ }
4002
+ setWidth (width) {
4003
+ const el = document.getElementById(`${this.elementId}_table`)
4004
+ if (el) {
4005
+ el.style.width = `${width}px`
4006
+ }
4007
+ }
4008
+ showLoading (options) {
4009
+ this.loadingDialog.show(options)
4010
+ }
4011
+ getColumnParameters (values) {
4012
+ const tableEl = document.getElementById(`${this.elementId}_table`)
4013
+ tableEl.style.tableLayout = 'auto'
4014
+ tableEl.style.width = 'auto'
4015
+ const bodyEl = document.getElementById(`${this.elementId}_body`)
4016
+ bodyEl.innerHTML = '<tr>' + values.map(c => `
4017
+ <td
4018
+ style='height: ${this.options.cellSize}px; line-height: ${this.options.cellSize}px;'
4019
+ >${c.value || '&nbsp;'}</td>
4020
+ `).join('') + '</tr>'
4021
+ // get height of the first data cell
4022
+ const cells = bodyEl.querySelectorAll(`tr:first-of-type td`)
4023
+ const tableContainerEl = document.getElementById(`${this.elementId}_tableContainer`)
4024
+ const cellHeight = cells[0].offsetHeight || cells[0].clientHeight
4025
+ const cellWidths = []
4026
+ let nonScrollableWidth = 0
4027
+ for (let i = 0; i < cells.length; i++) {
4028
+ if (i < this.options.leftColumns) {
4029
+ nonScrollableWidth += values[i].width || cells[i].offsetWidth || cells[i].clientWidth
4030
+ }
4031
+ cellWidths.push(values[i].width || cells[i].offsetWidth || cells[i].clientWidth)
4032
+ }
4033
+ // const cellWidth = firstDataCell.offsetWidth || firstDataCell.clientWidth
4034
+ // tableEl.style.width = ''
4035
+ this.columnParameters = {
4036
+ cellHeight,
4037
+ cellWidths,
4038
+ availableHeight: tableContainerEl.offsetHeight || tableContainerEl.clientHeight,
4039
+ availableWidth: tableContainerEl.offsetWidth || tableContainerEl.clientWidth,
4040
+ nonScrollableWidth,
4041
+ scrollableWidth: (tableContainerEl.offsetWidth || tableContainerEl.clientWidth) - nonScrollableWidth
4042
+ }
4043
+ bodyEl.innerHTML = ''
4044
+ tableEl.style.tableLayout = ''
4045
+ tableEl.style.width = ''
4046
+ return this.columnParameters
4047
+ }
4048
+ }
4049
+
4050
+ /* global d3 include WebsyDesigns */
4051
+ class WebsyChart {
4052
+ constructor (elementId, options) {
4053
+ const DEFAULTS = {
4054
+ margin: {
4055
+ top: 10,
4056
+ left: 3,
4057
+ bottom: 3,
4058
+ right: 3,
4059
+ axisBottom: 0,
4060
+ axisLeft: 0,
4061
+ axisRight: 0,
4062
+ axisTop: 0,
4063
+ legendBottom: 0,
4064
+ legendLeft: 0,
4065
+ legendRight: 0,
4066
+ legendTop: 0
4067
+ },
4068
+ orientation: 'vertical',
4069
+ colors: ['#5e4fa2', '#3288bd', '#66c2a5', '#abdda4', '#e6f598', '#fee08b', '#fdae61', '#f46d43', '#d53e4f', '#9e0142'],
4070
+ transitionDuration: 650,
4071
+ curveStyle: 'curveLinear',
4072
+ lineWidth: 2,
4073
+ forceZero: true,
4074
+ fontSize: 14,
4075
+ symbolSize: 20,
4076
+ showTrackingLine: true,
4077
+ showTooltip: true,
3176
4078
  showLegend: false,
3177
4079
  legendPosition: 'bottom',
3178
4080
  tooltipWidth: 200
@@ -3429,7 +4331,7 @@ if (this.options.data[side].scale === 'Time') {
3429
4331
  }
3430
4332
  }
3431
4333
  this.tooltip.setHeight(this.plotHeight)
3432
- this.tooltip.show(tooltipTitle, tooltipHTML, posOptions)
4334
+ this.options.showTooltip && this.tooltip.show(tooltipTitle, tooltipHTML, posOptions)
3433
4335
  // }
3434
4336
  // else {
3435
4337
  // xPoint = x0
@@ -4011,7 +4913,7 @@ function getBarX (d, i) {
4011
4913
  }
4012
4914
  }
4013
4915
  else {
4014
- if (this.options.grouping === 'stacked') {
4916
+ if (this.options.grouping !== 'stacked') {
4015
4917
  return this[xAxis](this.parseX(d.x.value))
4016
4918
  }
4017
4919
  else {
@@ -4021,7 +4923,7 @@ function getBarX (d, i) {
4021
4923
  }
4022
4924
  function getBarY (d, i) {
4023
4925
  if (this.options.orientation === 'horizontal') {
4024
- if (this.options.grouping === 'stacked') {
4926
+ if (this.options.grouping !== 'stacked') {
4025
4927
  return this[xAxis](this.parseX(d.x.value))
4026
4928
  }
4027
4929
  else {
@@ -4804,7 +5706,9 @@ const WebsyDesigns = {
4804
5706
  WebsyRouter,
4805
5707
  Router: WebsyRouter,
4806
5708
  WebsyTable,
5709
+ WebsyTable2,
4807
5710
  Table: WebsyTable,
5711
+ Table2: WebsyTable2,
4808
5712
  WebsyChart,
4809
5713
  Chart: WebsyChart,
4810
5714
  WebsyChartTooltip,
@@ -4821,6 +5725,7 @@ const WebsyDesigns = {
4821
5725
  Utils: WebsyUtils,
4822
5726
  ButtonGroup,
4823
5727
  WebsySwitch: Switch,
5728
+ Pager,
4824
5729
  Switch
4825
5730
  }
4826
5731
 
@@ -4844,5 +5749,3 @@ function usePayPal () {
4844
5749
  pps.src = '//www.paypal.com/sdk/js'
4845
5750
  document.getElementsByTagName('body')[0].appendChild(pps)
4846
5751
  }
4847
-
4848
- export default WebsyDesigns