SearchForm.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <script>
  2. import Vue from 'vue'
  3. import router from 'vuejs/route'
  4. import { mapState } from 'vuex'
  5. import SlimSelect from 'slim-select'
  6. export default {
  7. router,
  8. props: ['form'],
  9. data() {
  10. return {
  11. template: null,
  12. typed: null,
  13. autocomplete: null,
  14. slimFilters: [],
  15. $input: null
  16. // basePath: drupalSettings.path.baseUrl + drupalSettings.path.pathPrefix
  17. }
  18. },
  19. computed: {
  20. ...mapState({
  21. keys: state => state.Search.keys,
  22. term: state => state.Search.term,
  23. filters: state => state.Search.filters
  24. })
  25. },
  26. methods: {
  27. submit() {
  28. console.log("search submited", this.typed, this.autocomplete)
  29. // unfocus the text input to hide the keyboard on mobile device
  30. this.$input.blur()
  31. // New search is triggered by Base.vue with router (which will also fill the store)
  32. // cleaning slimfilters
  33. let filters = []
  34. this.slimFilters.forEach((filter, index) => {
  35. console.log('foreach filters', filter)
  36. if(filter){
  37. filters.push(filter)
  38. }
  39. })
  40. console.log('Cleaning filters',this.slimFilters, filters)
  41. // push router
  42. this.$router.push({name:'base', query:{
  43. keys:this.typed,
  44. term:this.autocomplete,
  45. filters:filters.join(',')
  46. }})
  47. // this.$router.push({
  48. // path:`${this.basePath}/base`,
  49. // query:{keys:this.typed,term:this.autocomplete}
  50. // })
  51. },
  52. onAutoCompleteSelect(event, ui){
  53. event.preventDefault();
  54. console.log('autoCompleteSelect', event, ui)
  55. this.typed = ui.item.label
  56. // we have to wait for typed watch to reset autocomplete before setting it
  57. setTimeout(function(){
  58. console.log('update autocomplete value after settimeout')
  59. this.autocomplete = ui.item.value
  60. if (this.typed !== this.keys || this.autocomplete !== this.term) {
  61. this.submit()
  62. }
  63. }.bind(this), 1)
  64. },
  65. onSelectFiltersChange(index, info){
  66. console.log('onSelectFiltersChange', index, info, this.filters)
  67. this.slimFilters[index] = info.value
  68. }
  69. },
  70. directives: {
  71. focus: {
  72. // directive definition
  73. inserted: function (el) {
  74. // do not focus the input as it popup the keyboard on mobile device
  75. // el.focus()
  76. }
  77. }
  78. },
  79. beforeMount() {
  80. // console.log('SearchForm beforeMount')
  81. if (this._props.form) {
  82. // console.log('SearchForm beforeMount if this._props.form ok')
  83. this.template = Vue.compile(this._props.form)
  84. // https://github.com/vuejs/vue/issues/9911
  85. this.$options.staticRenderFns = [];
  86. this._staticTrees = [];
  87. this.template.staticRenderFns.map(fn => (this.$options.staticRenderFns.push(fn)));
  88. }
  89. },
  90. watch: {
  91. typed(n, o){
  92. console.log('typed changed', o, n)
  93. // is changed also when autocomplete change it ...
  94. this.autocomplete = null
  95. },
  96. keys(n, o){
  97. console.log('keys changed', o, n)
  98. this.typed = n
  99. },
  100. term(n, o){
  101. console.log('autocomplete changed', o, n)
  102. this.autocomplete = n
  103. }
  104. },
  105. created() {
  106. this.typed = this.keys
  107. this.autocomplete = this.term
  108. },
  109. mounted(){
  110. // console.log('SearchForm mounted')
  111. Drupal.attachBehaviors(this.$el);
  112. // get the search input
  113. this.$input = this.$el.querySelector('#edit-search')
  114. // // focus on input
  115. // $input.focus()
  116. // Catch the jquery ui events for autocmplete widget
  117. jQuery(this.$input).on('autocompleteselect', this.onAutoCompleteSelect);
  118. // customize the select filters
  119. // http://slimselectjs.com/options
  120. const selects = this.$el.querySelectorAll('select')
  121. selects.forEach((selectElement, index) => {
  122. // get the first option to make the placeholder then empty it
  123. const placeholder_option = selectElement.querySelector('option:first-child')
  124. // console.log('placeholder_option', placeholder_option);
  125. const placeholder = placeholder_option.innerText
  126. placeholder_option.removeAttribute("value")
  127. placeholder_option.setAttribute("data-placeholder", true)
  128. placeholder_option.innerHTML = ''
  129. new SlimSelect({
  130. select: selectElement,
  131. placeholder: placeholder,
  132. // allowDeselect: true
  133. allowDeselectOption: true,
  134. showSearch: false,
  135. closeOnSelect: true,
  136. onChange: (info) => {
  137. this.onSelectFiltersChange(index, info)
  138. }
  139. })
  140. })
  141. },
  142. render(h) {
  143. // console.log('searchForm render')
  144. if (!this.template) {
  145. return h('span', 'Loading ...')
  146. } else {
  147. return this.template.render.call(this)
  148. }
  149. }
  150. }
  151. </script>
  152. <style lang="scss" scoped>
  153. </style>