SearchForm.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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. onClickFilters(e){
  70. console.log('onClickFilters legend', e)
  71. e.target.closest('fieldset').classList.toggle('open')
  72. // TODO: reset the filters oon close
  73. }
  74. },
  75. directives: {
  76. focus: {
  77. // directive definition
  78. inserted: function (el) {
  79. // do not focus the input as it popup the keyboard on mobile device
  80. // el.focus()
  81. }
  82. }
  83. },
  84. beforeMount() {
  85. // console.log('SearchForm beforeMount')
  86. if (this._props.form) {
  87. // console.log('SearchForm beforeMount if this._props.form ok')
  88. this.template = Vue.compile(this._props.form)
  89. // https://github.com/vuejs/vue/issues/9911
  90. this.$options.staticRenderFns = [];
  91. this._staticTrees = [];
  92. this.template.staticRenderFns.map(fn => (this.$options.staticRenderFns.push(fn)));
  93. }
  94. },
  95. watch: {
  96. typed(n, o){
  97. console.log('typed changed', o, n)
  98. // is changed also when autocomplete change it ...
  99. this.autocomplete = null
  100. },
  101. keys(n, o){
  102. console.log('keys changed', o, n)
  103. this.typed = n
  104. },
  105. term(n, o){
  106. console.log('autocomplete changed', o, n)
  107. this.autocomplete = n
  108. }
  109. },
  110. created() {
  111. this.typed = this.keys
  112. this.autocomplete = this.term
  113. },
  114. mounted(){
  115. // console.log('SearchForm mounted')
  116. Drupal.attachBehaviors(this.$el);
  117. // get the search input
  118. this.$input = this.$el.querySelector('#edit-search')
  119. // // focus on input
  120. // $input.focus()
  121. // Catch the jquery ui events for autocmplete widget
  122. jQuery(this.$input).on('autocompleteselect', this.onAutoCompleteSelect);
  123. // customize the select filters
  124. // http://slimselectjs.com/options
  125. const selects = this.$el.querySelectorAll('select')
  126. selects.forEach((selectElement, index) => {
  127. // get the first option to make the placeholder then empty it
  128. const placeholder_option = selectElement.querySelector('option:first-child')
  129. // console.log('placeholder_option', placeholder_option);
  130. const placeholder = placeholder_option.innerText
  131. placeholder_option.removeAttribute("value")
  132. placeholder_option.setAttribute("data-placeholder", true)
  133. placeholder_option.innerHTML = ''
  134. new SlimSelect({
  135. select: selectElement,
  136. placeholder: placeholder,
  137. // allowDeselect: true
  138. allowDeselectOption: true,
  139. showSearch: false,
  140. closeOnSelect: true,
  141. onChange: (info) => {
  142. this.onSelectFiltersChange(index, info)
  143. }
  144. })
  145. })
  146. },
  147. render(h) {
  148. // console.log('searchForm render')
  149. if (!this.template) {
  150. return h('span', $t('default.Loading…'))
  151. } else {
  152. return this.template.render.call(this)
  153. }
  154. }
  155. }
  156. </script>
  157. <style lang="scss" scoped>
  158. </style>