@websy/websy-designs 1.3.4 → 1.3.5

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.
@@ -2465,7 +2465,7 @@ class WebsyLogin {
2465
2465
  }
2466
2466
  }
2467
2467
 
2468
- /* global */
2468
+ /* global WebsyDesigns */
2469
2469
  class WebsyNavigationMenu {
2470
2470
  constructor (elementId, options) {
2471
2471
  this.options = Object.assign({}, {
@@ -2473,20 +2473,28 @@ class WebsyNavigationMenu {
2473
2473
  orientation: 'horizontal',
2474
2474
  parentMap: {},
2475
2475
  childIndentation: 10,
2476
- activeSymbol: 'none'
2476
+ activeSymbol: 'none',
2477
+ enableSearch: false,
2478
+ searchProp: 'text',
2479
+ menuIcon: `<svg viewbox="0 0 40 40" width="30" height="40">
2480
+ <rect x="0" y="0" width="30" height="4" rx="2"></rect>
2481
+ <rect x="0" y="12" width="30" height="4" rx="2"></rect>
2482
+ <rect x="0" y="24" width="30" height="4" rx="2"></rect>
2483
+ </svg>`,
2484
+ searchOptions: {}
2477
2485
  }, options)
2478
2486
  if (!elementId) {
2479
2487
  console.log('No element Id provided for Websy Menu')
2480
2488
  return
2481
2489
  }
2490
+ this.maxLevel = 0
2482
2491
  const el = document.getElementById(elementId)
2483
2492
  if (el) {
2484
2493
  this.elementId = elementId
2485
2494
  this.lowestLevel = 0
2486
2495
  this.flatItems = []
2487
2496
  this.itemMap = {}
2488
- this.flattenItems(0, this.options.items)
2489
- console.log(this.flatItems)
2497
+ this.flattenItems(0, this.options.items)
2490
2498
  el.classList.add(`websy-${this.options.orientation}-list-container`)
2491
2499
  el.classList.add('websy-menu')
2492
2500
  if (this.options.align) {
@@ -2498,27 +2506,27 @@ class WebsyNavigationMenu {
2498
2506
  if (this.options.classes) {
2499
2507
  this.options.classes.split(' ').forEach(c => el.classList.add(c))
2500
2508
  }
2501
- el.addEventListener('click', this.handleClick.bind(this))
2509
+ el.addEventListener('click', this.handleClick.bind(this))
2502
2510
  this.render()
2503
2511
  }
2504
2512
  }
2505
- flattenItems (index, items, level = 0) {
2513
+ flattenItems (index, items, level = 0, path = '') {
2506
2514
  if (items[index]) {
2507
2515
  this.lowestLevel = Math.max(level, this.lowestLevel)
2508
2516
  items[index].id = items[index].id || `${this.elementId}_${this.normaliseString(items[index].text)}`
2509
- this.itemMap[items[index].id] = items[index]
2510
2517
  items[index].level = level
2518
+ items[index].hasChildren = items[index].items && items[index].items.length > 0
2519
+ items[index].path = path !== '' ? `${path}::${items[index].id}` : items[index].id
2520
+ this.itemMap[items[index].id] = Object.assign({}, items[index])
2511
2521
  this.flatItems.push(items[index])
2512
2522
  if (items[index].items) {
2513
- this.flattenItems(0, items[index].items, level + 1)
2523
+ this.flattenItems(0, items[index].items, level + 1, items[index].path)
2514
2524
  }
2515
- this.flattenItems(++index, items, level)
2525
+ this.flattenItems(++index, items, level, path)
2516
2526
  }
2517
2527
  }
2518
2528
  handleClick (event) {
2519
- if (event.target.classList.contains('websy-menu-icon') ||
2520
- event.target.nodeName === 'svg' ||
2521
- event.target.nodeName === 'rect') {
2529
+ if (event.target.classList.contains('websy-menu-icon')) {
2522
2530
  this.toggleMobileMenu()
2523
2531
  }
2524
2532
  if (event.target.classList.contains('websy-menu-header')) {
@@ -2526,7 +2534,7 @@ class WebsyNavigationMenu {
2526
2534
  if (event.target.classList.contains('trigger-item') && item.level === this.lowestLevel) {
2527
2535
  this.toggleMobileMenu('remove')
2528
2536
  }
2529
- if (item.items) {
2537
+ if (item.hasChildren === true) {
2530
2538
  event.target.classList.toggle('menu-open')
2531
2539
  this.toggleMenu(item.id)
2532
2540
  }
@@ -2535,6 +2543,42 @@ class WebsyNavigationMenu {
2535
2543
  this.toggleMobileMenu()
2536
2544
  }
2537
2545
  }
2546
+ handleSearch (searchText) {
2547
+ const el = document.getElementById(this.elementId)
2548
+ let lowestItems = this.flatItems.filter(d => d.level === this.maxLevel)
2549
+ let visibleItems = lowestItems
2550
+ let defaultMethod = 'remove'
2551
+ if (searchText.length > 1) {
2552
+ defaultMethod = 'add'
2553
+ visibleItems = lowestItems.filter(d => d[this.options.searchProp].toLowerCase().indexOf(searchText.toLowerCase()) !== -1)
2554
+ }
2555
+ // hide everything
2556
+ const textEls = el.querySelectorAll(`div.websy-menu-header`)
2557
+ for (let t = 0; t < textEls.length; t++) {
2558
+ textEls[t].classList[defaultMethod]('websy-hidden')
2559
+ }
2560
+ const listEls = el.querySelectorAll(`ul.websy-child-list`)
2561
+ for (let l = 0; l < listEls.length; l++) {
2562
+ listEls[l].classList.add('websy-menu-collapsed')
2563
+ }
2564
+ if (searchText.length > 1) {
2565
+ visibleItems.forEach(d => {
2566
+ // show the item and open the list
2567
+ let pathParts = d.path.split('::')
2568
+ pathParts.forEach(p => {
2569
+ const textEl = document.getElementById(p)
2570
+ if (textEl) {
2571
+ textEl.classList.remove('websy-hidden')
2572
+ }
2573
+ const listEl = document.getElementById(`${p}_list`)
2574
+ if (listEl) {
2575
+ listEl.classList.remove('websy-menu-collapsed')
2576
+ }
2577
+ })
2578
+ })
2579
+ }
2580
+ console.log('visibleItems', visibleItems)
2581
+ }
2538
2582
  normaliseString (text) {
2539
2583
  return text.replace(/-/g, '').replace(/\s/g, '_')
2540
2584
  }
@@ -2545,14 +2589,10 @@ class WebsyNavigationMenu {
2545
2589
  if (this.options.collapsible === true) {
2546
2590
  html += `
2547
2591
  <div id='${this.elementId}_menuIcon' class='websy-menu-icon'>
2548
- <svg viewbox="0 0 40 40" width="30" height="40">
2549
- <rect x="0" y="0" width="30" height="4" rx="2"></rect>
2550
- <rect x="0" y="12" width="30" height="4" rx="2"></rect>
2551
- <rect x="0" y="24" width="30" height="4" rx="2"></rect>
2552
- </svg>
2592
+ ${this.options.menuIcon}
2553
2593
  </div>
2554
2594
  `
2555
- }
2595
+ }
2556
2596
  if (this.options.logo) {
2557
2597
  if (Array.isArray(this.options.logo.classes)) {
2558
2598
  this.options.logo.classes = this.options.logo.classes.join(' ')
@@ -2568,14 +2608,25 @@ class WebsyNavigationMenu {
2568
2608
  <div id="${this.elementId}_menuContainer" class="websy-menu-block-container">
2569
2609
  `
2570
2610
  }
2571
- html += this.renderBlock(this.options.items, 'main', 0)
2611
+ if (this.options.enableSearch === true) {
2612
+ html += `
2613
+ <div id='${this.elementId}_search' class='websy-menu-search'></div>
2614
+ `
2615
+ }
2616
+ html += this.renderBlock(this.elementId, this.elementId, this.options.items, 'main', 0)
2572
2617
  html += `</div>`
2573
2618
  el.innerHTML = html
2619
+ if (this.options.enableSearch === true) {
2620
+ this.search = new WebsyDesigns.Search(`${this.elementId}_search`, Object.assign({}, {
2621
+ onSearch: this.handleSearch.bind(this)
2622
+ }, this.options.searchOptions))
2623
+ }
2574
2624
  }
2575
2625
  }
2576
- renderBlock (items, block, level = 0) {
2626
+ renderBlock (id, path, items, block, level = 0) {
2627
+ this.maxLevel = Math.max(this.maxLevel, level)
2577
2628
  let html = `
2578
- <ul class='websy-${this.options.orientation}-list ${level > 0 ? 'websy-child-list' : ''} ${(block !== 'main' ? 'websy-menu-collapsed' : '')}' id='${this.elementId}_${block}_list'
2629
+ <ul class='websy-${this.options.orientation}-list ${level > 0 ? 'websy-child-list' : ''} ${(block !== 'main' ? 'websy-menu-collapsed' : '')}' id='${id}_list' data-path='${path}'
2579
2630
  `
2580
2631
  if (block !== 'main') {
2581
2632
  html += ` data-collapsed='${(block !== 'main' ? 'true' : 'false')}'`
@@ -2593,13 +2644,14 @@ class WebsyNavigationMenu {
2593
2644
  html += `
2594
2645
  <li class='websy-${this.options.orientation}-list-item ${items[i].alwaysOpen === true ? 'always-open' : ''}'>
2595
2646
  <div class='websy-menu-header ${items[i].classes || ''} ${selected} ${active}'
2596
- id='${blockId}'
2597
- data-id='${currentBlock}'
2598
- data-menu-id='${this.elementId}_${currentBlock}_list'
2599
- data-popout-id='${level > 1 ? block : currentBlock}'
2600
- data-text='${items[i].isLink !== true ? items[i].text : ''}'
2601
- style='padding-left: ${level * this.options.childIndentation}px'
2602
- ${(items[i].attributes && items[i].attributes.join(' ')) || ''}
2647
+ id='${blockId}'
2648
+ data-id='${currentBlock}'
2649
+ data-path='${items[i].path}'
2650
+ data-menu-id='${this.elementId}_${currentBlock}_list'
2651
+ data-popout-id='${level > 1 ? block : currentBlock}'
2652
+ data-text='${items[i].isLink !== true ? items[i].text : ''}'
2653
+ style='padding-left: ${level * this.options.childIndentation}px'
2654
+ ${(items[i].attributes && items[i].attributes.join(' ')) || ''}
2603
2655
  >
2604
2656
  `
2605
2657
  if (this.options.orientation === 'horizontal') {
@@ -2619,9 +2671,9 @@ class WebsyNavigationMenu {
2619
2671
  <span class='${items[i].items && items[i].items.length > 0 ? 'menu-carat' : ''}'></span>
2620
2672
  `
2621
2673
  if (this.options.orientation === 'vertical') {
2622
- html += `
2623
- &nbsp;
2624
- `
2674
+ // html += `
2675
+ // &nbsp;
2676
+ // `
2625
2677
  }
2626
2678
  if (items[i].isLink === true && items[i].href) {
2627
2679
  html += `<a href='${items[i].href}'>${items[i].text}</a>`
@@ -2630,7 +2682,7 @@ class WebsyNavigationMenu {
2630
2682
  </div>
2631
2683
  `
2632
2684
  if (items[i].items) {
2633
- html += this.renderBlock(items[i].items, currentBlock, items[i].level + 1)
2685
+ html += this.renderBlock(blockId, items[i].path, items[i].items, currentBlock, items[i].level + 1)
2634
2686
  }
2635
2687
  // map the item to it's parent
2636
2688
  if (block && block !== 'main') {
@@ -2647,6 +2699,8 @@ class WebsyNavigationMenu {
2647
2699
  }
2648
2700
  toggleMenu (id) {
2649
2701
  const el = document.getElementById(`${id}_list`)
2702
+ // const menuId = el.getAttribute('data-menu-id')
2703
+ // const menuEl = document.getElementById(menuId)
2650
2704
  if (el) {
2651
2705
  el.classList.toggle('websy-menu-collapsed')
2652
2706
  }
@@ -3584,7 +3638,14 @@ class WebsyRouter {
3584
3638
  this.previousView = ''
3585
3639
  this.currentView = ''
3586
3640
  this.currentViewMain = ''
3587
- this.currentParams = {}
3641
+ this.currentParams = {
3642
+ path: '',
3643
+ items: {}
3644
+ }
3645
+ this.previousParams = {
3646
+ path: '',
3647
+ items: {}
3648
+ }
3588
3649
  this.controlPressed = false
3589
3650
  this.usesHTMLSuffix = window.location.pathname.indexOf('.htm') !== -1
3590
3651
  window.addEventListener('popstate', this.onPopState.bind(this))
@@ -3625,10 +3686,11 @@ class WebsyRouter {
3625
3686
  }
3626
3687
  }
3627
3688
  }
3628
- addUrlParams (params) {
3689
+ addUrlParams (params, reloadView = false) {
3629
3690
  if (typeof params === 'undefined') {
3630
3691
  return
3631
3692
  }
3693
+ this.previousParams = Object.assign({}, this.currentParams)
3632
3694
  const output = {
3633
3695
  path: '',
3634
3696
  items: {}
@@ -3650,6 +3712,9 @@ class WebsyRouter {
3650
3712
  history.pushState({
3651
3713
  inputPath
3652
3714
  }, inputPath, `${inputPath}?${path}`)
3715
+ if (reloadView === true) {
3716
+ this.showView(this.currentView, this.currentParams, 'main')
3717
+ }
3653
3718
  }
3654
3719
  buildUrlPath (params) {
3655
3720
  let path = []
@@ -3678,6 +3743,7 @@ class WebsyRouter {
3678
3743
  }
3679
3744
  }
3680
3745
  formatParams (params) {
3746
+ this.previousParams = Object.assign({}, this.currentParams)
3681
3747
  const output = {
3682
3748
  path: params,
3683
3749
  items: {}
@@ -3897,6 +3963,10 @@ class WebsyRouter {
3897
3963
  if (this.previousView !== this.currentView || group !== 'main') {
3898
3964
  this.showComponents(view)
3899
3965
  this.publish('show', [view, params, group])
3966
+ }
3967
+ if (this.previousView === this.currentView && this.previousParams.path !== this.currentParams.path) {
3968
+ this.showComponents(view)
3969
+ this.publish('show', [view, params, group])
3900
3970
  }
3901
3971
  }
3902
3972
  reloadCurrentView () {
@@ -3912,17 +3982,14 @@ class WebsyRouter {
3912
3982
  let groupActiveView
3913
3983
  let params = {}
3914
3984
  let newPath = inputPath
3915
- if (inputPath === this.options.defaultView && this.usesHTMLSuffix === false) {
3985
+ if (inputPath.split('?')[0] === this.options.defaultView && this.usesHTMLSuffix === false) {
3916
3986
  inputPath = inputPath.replace(this.options.defaultView, '/')
3917
3987
  }
3918
3988
  if (this.options.persistentParameters === true) {
3919
3989
  if (inputPath.indexOf('?') === -1 && this.queryParams) {
3920
3990
  inputPath += `?${this.queryParams}`
3921
3991
  }
3922
- }
3923
- else {
3924
- this.currentParams = {}
3925
- }
3992
+ }
3926
3993
  if (this.usesHTMLSuffix === true) {
3927
3994
  if (inputPath.indexOf('?') === -1) {
3928
3995
  inputPath = `?view=${inputPath}`
@@ -3943,7 +4010,11 @@ class WebsyRouter {
3943
4010
  inputPath = parts[0]
3944
4011
  }
3945
4012
  else if (group === this.options.defaultGroup) {
3946
- this.currentParams = {}
4013
+ this.previousParams = Object.assign({}, this.currentParams)
4014
+ this.currentParams = {
4015
+ path: '',
4016
+ items: {}
4017
+ }
3947
4018
  }
3948
4019
  if (event) {
3949
4020
  if (event.target && event.target.classList.contains(this.options.triggerToggleClass)) {
@@ -4112,7 +4183,7 @@ class WebsySearch {
4112
4183
  this.elementId = elementId
4113
4184
  const DEFAULTS = {
4114
4185
  searchIcon: `<svg class='search' width="20" height="20" viewBox="0 0 512 512"><path d="M221.09,64A157.09,157.09,0,1,0,378.18,221.09,157.1,157.1,0,0,0,221.09,64Z" style="fill:none;stroke:#000;stroke-miterlimit:10;stroke-width:32px"/><line x1="338.29" y1="338.29" x2="448" y2="448" style="fill:none;stroke:#000;stroke-linecap:round;stroke-miterlimit:10;stroke-width:32px"/></svg>`,
4115
- clearIcon: `<svg class='clear' xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 512 512"><title>ionicons-v5-l</title><line x1="368" y1="368" x2="144" y2="144" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/><line x1="368" y1="144" x2="144" y2="368" style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/></svg>`,
4186
+ clearIcon: `<svg 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>`,
4116
4187
  placeholder: 'Search',
4117
4188
  searchTimeout: 500,
4118
4189
  minLength: 2
@@ -4122,12 +4193,15 @@ class WebsySearch {
4122
4193
  const el = document.getElementById(elementId)
4123
4194
  if (el) {
4124
4195
  // el.addEventListener('click', this.handleClick.bind(this))
4196
+ el.addEventListener('click', this.handleClick.bind(this))
4125
4197
  el.addEventListener('keyup', this.handleKeyUp.bind(this))
4126
4198
  el.innerHTML = `
4127
4199
  <div class='websy-search-input-container'>
4128
4200
  ${this.options.searchIcon}
4129
4201
  <input id='${this.elementId}_search' class='websy-search-input' placeholder='${this.options.placeholder || 'Search'}'>
4130
- ${this.options.clearIcon}
4202
+ <div class='clear websy-hidden' id='${this.elementId}_clear'>
4203
+ ${this.options.clearIcon}
4204
+ </div>
4131
4205
  </div>
4132
4206
  `
4133
4207
  }
@@ -4135,11 +4209,25 @@ class WebsySearch {
4135
4209
  console.log('No element found with Id', elementId)
4136
4210
  }
4137
4211
  }
4212
+ handleClick (event) {
4213
+ if (event.target.classList.contains('clear')) {
4214
+ const inputEl = document.getElementById(`${this.elementId}_search`)
4215
+ inputEl.value = ''
4216
+ this.options.onSearch('')
4217
+ }
4218
+ }
4138
4219
  handleKeyUp (event) {
4139
4220
  if (event.target.classList.contains('websy-search-input')) {
4140
4221
  if (this.searchTimeoutFn) {
4141
4222
  clearTimeout(this.searchTimeoutFn)
4142
4223
  }
4224
+ const clearEl = document.getElementById(`${this.elementId}_clear`)
4225
+ if (event.target.value.length > 0) {
4226
+ clearEl.classList.remove('websy-hidden')
4227
+ }
4228
+ else {
4229
+ clearEl.classList.add('websy-hidden')
4230
+ }
4143
4231
  if (event.target.value.length >= this.options.minLength) {
4144
4232
  this.searchTimeoutFn = setTimeout(() => {
4145
4233
  if (this.options.onSearch) {