You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

233 lines
7.0 KiB

  1. import $ from 'jquery';
  2. const maxTextLength = 48;
  3. export class IHKSearchTiles {
  4. static lastReqId = "";
  5. constructor(tileWrapper) {
  6. tileWrapper.addClass("initiated");
  7. this.itemTitles = tileWrapper[0].getElementsByTagName('a');
  8. const regex = new RegExp("^[a-zA-Z0-9äÄöÖüÜß._\b ]+$");
  9. this.shortenTileText(this.itemTitles);
  10. // find input element
  11. this.input = document.getElementById("search-field-infobar");
  12. if (!this.input) {
  13. return;
  14. }
  15. this.objId = this.input.getAttribute("data-tile-search");
  16. this.formAction = document.getElementById("mainTeaserSearchForm");
  17. this.searchButton = this.formAction.querySelector("button");
  18. // if we have no object id configured we do not want to perform a dynamic search
  19. if (this.objId == null || this.objId.trim().length === 0 || this.formAction == null) {
  20. return;
  21. }
  22. this.rateLimit = this.checkRateLimit(this.input.getAttribute("data-tile-search-rl"));
  23. // create the search button under the tiles
  24. this.allResultButton = document.createElement("span");
  25. this.allResultButton.classList.add("all-button-wrapper");
  26. this.buttonString = '<div class=\"btn has-icon icon-small-arrow-right-simple\">Alle Suchergebnisse</div>';
  27. this.allResultButton.innerHTML = this.buttonString;
  28. this.allResultButton.addEventListener("click", () => {
  29. this.searchButton.click();
  30. });
  31. const tiles = tileWrapper[0].innerHTML;
  32. let coolDown = false;
  33. let sendValue = "";
  34. let lastValue = "";
  35. let lastSend = null;
  36. this.doAjaxCall.bind(this);
  37. this.shortenTileText.bind(this);
  38. this.input.addEventListener("keyup", function (event) {
  39. if (!regex.test(event.key)) {
  40. return;
  41. }
  42. // read the current value from the input field
  43. let input = event.target;
  44. let currentText = input.value;
  45. let self = this;
  46. let delta = (lastSend === null) ? this.rateLimit + 1 : new Date().getTime() - lastSend.getTime();
  47. if (!coolDown && currentText.length > 1) {
  48. if (delta > this.rateLimit) {
  49. sendValue = currentText;
  50. // trigger the ajax call and the search action here
  51. this.doAjaxCall(input, sendValue);
  52. lastSend = new Date();
  53. coolDown = true;
  54. }
  55. setTimeout(function () {
  56. coolDown = false;
  57. if (lastValue != sendValue && lastValue.length > 1) {
  58. self.doAjaxCall(input, lastValue);
  59. sendValue = lastValue;
  60. lastSend = new Date();
  61. }
  62. }, this.rateLimit);
  63. } else if (currentText.length < 2) {
  64. // show initial tiles here
  65. let newTiles = document.getElementById("tilesSearch");
  66. let span = newTiles.nextElementSibling;
  67. newTiles.innerHTML = tiles;
  68. if (span) {
  69. span.remove();
  70. }
  71. }
  72. lastValue = currentText;
  73. }.bind(this));
  74. // remove initial search input in case of the user uses the back function of the browser
  75. window.onload = () => {
  76. this.input.value = "";
  77. };
  78. }
  79. shortenTileText(tiles) {
  80. for (let tile of tiles) {
  81. if (tile.innerText.length > maxTextLength) {
  82. tile.innerText = tile.innerText.substring(0, maxTextLength) + '…';
  83. }
  84. }
  85. }
  86. doAjaxCall(ajaxObj, query) {
  87. const self = this;
  88. const q = query;
  89. const objId = ajaxObj.getAttribute("data-tile-search");
  90. const url = "/blueprint/servlet/serviceport/search/" + objId;
  91. const urlAndQuery = url + "?query=" + query;
  92. const requestId = Math.floor(Math.random() * 100000);
  93. IHKSearchTiles.lastReqId = requestId;
  94. $.ajax({
  95. url: urlAndQuery,
  96. method: "GET",
  97. timeout: 0,
  98. success: function (result) {
  99. if (requestId == IHKSearchTiles.lastReqId) {
  100. let tiles = document.getElementById("tilesSearch");
  101. // replace tiles here
  102. tiles.innerHTML = result;
  103. // find tile a and shorten the text if needed
  104. let itemTitles = tiles.getElementsByClassName('item-title');
  105. self.shortenTileText(itemTitles);
  106. // add the "all results" button
  107. tiles.insertAdjacentElement("afterend", self.allResultButton);
  108. }
  109. }
  110. });
  111. }
  112. checkRateLimit(rl) {
  113. if (rl.trim().length > 0) {
  114. let num = parseInt(rl);
  115. if (num >= 100) {
  116. return num;
  117. } else {
  118. return 300;
  119. }
  120. }
  121. return 300;
  122. }
  123. }
  124. class IHKExtendedSearch {
  125. constructor(section) {
  126. this.section = section.addClass('initiated');
  127. $('#search-expand-collapse').on('click', (e) => {
  128. e.preventDefault();
  129. $(e.currentTarget).toggleClass('open');
  130. this.section.stop().slideToggle(500, 'swing');
  131. });
  132. section.find('.ev-search-btn').on('click', (e) => {
  133. e.preventDefault();
  134. const target = $(e.currentTarget);
  135. target.next('.ev-filter').stop().slideToggle(400, 'easeOutQuad');
  136. window.requestAnimationFrame(() => {
  137. target.toggleClass('open');
  138. })
  139. });
  140. section.find('label.acc a').each((i, el) => {
  141. new FormAccordion($(el));
  142. });
  143. section.find('.reset').on('click', (e) => {
  144. e.preventDefault();
  145. const form = $(e.currentTarget).closest('form');
  146. form[0].reset();
  147. form.find('.half-checked').removeClass('half-checked');
  148. $('html, body').animate({
  149. scrollTop: form.offset().top - 120
  150. }, 500, 'easeOutQuad');
  151. });
  152. /*
  153. $('.datepicker').each((i, el) => {
  154. $(el).datepicker({ changeYear: true, changeMonth: true});
  155. });
  156. */
  157. }
  158. }
  159. class FormAccordion {
  160. constructor(toggle) {
  161. const t = this;
  162. this.toggle = toggle;
  163. this.label = this.toggle.parent('label');
  164. this.checkbox = this.label.prev('input[type="checkbox"]');
  165. this.subs = this.label.next('.ev-filter');
  166. this.toggle.on('click', (e) => {
  167. e.preventDefault();
  168. e.stopPropagation();
  169. this.label.toggleClass('open');
  170. this.subs.stop().slideToggle(400, 'swing');
  171. })
  172. this.subs.find('input[type="checkbox"]').on('change', () => {
  173. this.checkSelection();
  174. })
  175. this.checkbox.on('change', (e) => {
  176. const isChecked = $(e.currentTarget).removeClass('half-checked').prop('checked');
  177. this.subs.find('input[type="checkbox"]').prop('checked', isChecked);
  178. })
  179. this.checkSelection();
  180. }
  181. checkSelection() {
  182. const checked = this.subs.find('input[type="checkbox"]:checked').length;
  183. const unchecked = this.subs.find('input[type="checkbox"]:not(:checked)').length;
  184. if (checked + unchecked === 0) {
  185. this.checkbox.removeClass('half-checked');
  186. return;
  187. }
  188. if (checked === 0) {
  189. this.checkbox.prop('checked', false).removeClass('half-checked');
  190. } else if (unchecked === 0) {
  191. this.checkbox.prop('checked', true).removeClass('half-checked');
  192. } else {
  193. this.checkbox.prop('checked', false).addClass('half-checked');
  194. }
  195. }
  196. }
  197. export default IHKExtendedSearch;
  198. $('body').on('ihk-init dynamic-component-loaded', function () {
  199. $('.extended-search:not(.initiated)').each(function (i) {
  200. new IHKExtendedSearch($(this));
  201. });
  202. });