Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 

253 řádky
7.8 KiB

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