No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 

229 líneas
6.9 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", () => {
  30. this.searchButton.click();
  31. });
  32. const tiles = tileWrapper[0].innerHTML;
  33. let coolDown = false;
  34. let sendValue = "";
  35. let lastValue = "";
  36. let lastSend = null;
  37. this.doAjaxCall.bind(this);
  38. this.shortenTileText.bind(this);
  39. this.input.addEventListener("keyup", (event) => {
  40. if (!regex.test(event.key)) {
  41. return;
  42. }
  43. // read the current value from the input field
  44. let input = event.target;
  45. let currentText = input.value;
  46. let self = this;
  47. let delta = (lastSend === null) ? this.rateLimit + 1 : new Date().getTime() - lastSend.getTime();
  48. if (!coolDown && currentText.length > 1) {
  49. if (delta > this.rateLimit) {
  50. sendValue = currentText;
  51. // trigger the ajax call and the search action here
  52. this.doAjaxCall(input, sendValue, this.tileWrapper[0]);
  53. lastSend = new Date();
  54. coolDown = true;
  55. }
  56. setTimeout(() => {
  57. coolDown = false;
  58. if (lastValue !== sendValue && lastValue.length > 1) {
  59. self.doAjaxCall(input, lastValue, this.tileWrapper[0]);
  60. sendValue = lastValue;
  61. lastSend = new Date();
  62. }
  63. }, this.rateLimit);
  64. } else if (currentText.length < 2) {
  65. // show initial tiles here
  66. let span = this.tileWrapper.nextElementSibling;
  67. this.tileWrapper.innerHTML = tiles;
  68. if (span) {
  69. span.remove();
  70. }
  71. }
  72. lastValue = currentText;
  73. });
  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, tiles) {
  87. const self = this;
  88. const objId = ajaxObj.getAttribute("data-tile-search");
  89. const url = "/blueprint/servlet/serviceport/search/" + objId;
  90. const urlAndQuery = url + "?query=" + query;
  91. const requestId = Math.floor(Math.random() * 100000);
  92. lastReqId = requestId;
  93. $.ajax({
  94. url: urlAndQuery,
  95. method: "GET",
  96. timeout: 0,
  97. success: function (result) {
  98. if (requestId === lastReqId) {
  99. // replace tiles here
  100. tiles.innerHTML = result;
  101. // find tile a and shorten the text if needed
  102. let itemTitles = tiles.getElementsByClassName('item-title');
  103. self.shortenTileText(itemTitles);
  104. // add the "all results" button
  105. tiles.insertAdjacentElement("afterend", self.allResultButton);
  106. }
  107. }
  108. });
  109. }
  110. checkRateLimit(rl) {
  111. if (rl.trim().length > 0) {
  112. let num = parseInt(rl);
  113. if (num >= 100) {
  114. return num;
  115. } else {
  116. return 300;
  117. }
  118. }
  119. return 300;
  120. }
  121. }
  122. class IHKExtendedSearch {
  123. constructor(section) {
  124. this.section = section.addClass('initiated');
  125. $('#search-expand-collapse').on('click', (e) => {
  126. e.preventDefault();
  127. $(e.currentTarget).toggleClass('open');
  128. this.section.stop().slideToggle(500, 'swing');
  129. });
  130. section.find('.ev-search-btn').on('click', (e) => {
  131. e.preventDefault();
  132. const target = $(e.currentTarget);
  133. target.next('.ev-filter').stop().slideToggle(400, 'easeOutQuad');
  134. window.requestAnimationFrame(() => {
  135. target.toggleClass('open');
  136. })
  137. });
  138. section.find('label.acc a').each((i, el) => {
  139. new FormAccordion($(el));
  140. });
  141. section.find('.reset').on('click', (e) => {
  142. e.preventDefault();
  143. const form = $(e.currentTarget).closest('form');
  144. form[0].reset();
  145. form.find('.half-checked').removeClass('half-checked');
  146. $('html, body').animate({
  147. scrollTop: form.offset().top - 120
  148. }, 500, 'easeOutQuad');
  149. });
  150. /*
  151. $('.datepicker').each((i, el) => {
  152. $(el).datepicker({ changeYear: true, changeMonth: true});
  153. });
  154. */
  155. }
  156. }
  157. class FormAccordion {
  158. constructor(toggle) {
  159. this.toggle = toggle;
  160. this.label = this.toggle.parent('label');
  161. this.checkbox = this.label.prev('input[type="checkbox"]');
  162. this.subs = this.label.next('.ev-filter');
  163. this.toggle.on('click', (e) => {
  164. e.preventDefault();
  165. e.stopPropagation();
  166. this.label.toggleClass('open');
  167. this.subs.stop().slideToggle(400, 'swing');
  168. })
  169. this.subs.find('input[type="checkbox"]').on('change', () => {
  170. this.checkSelection();
  171. })
  172. this.checkbox.on('change', (e) => {
  173. const isChecked = $(e.currentTarget).removeClass('half-checked').prop('checked');
  174. this.subs.find('input[type="checkbox"]').prop('checked', isChecked);
  175. })
  176. this.checkSelection();
  177. }
  178. checkSelection() {
  179. const checked = this.subs.find('input[type="checkbox"]:checked').length;
  180. const unchecked = this.subs.find('input[type="checkbox"]:not(:checked)').length;
  181. if (checked + unchecked === 0) {
  182. this.checkbox.removeClass('half-checked');
  183. return;
  184. }
  185. if (checked === 0) {
  186. this.checkbox.prop('checked', false).removeClass('half-checked');
  187. } else if (unchecked === 0) {
  188. this.checkbox.prop('checked', true).removeClass('half-checked');
  189. } else {
  190. this.checkbox.prop('checked', false).addClass('half-checked');
  191. }
  192. }
  193. }
  194. export default IHKExtendedSearch;
  195. $('body').on('ihk-init dynamic-component-loaded', function () {
  196. $('.extended-search:not(.initiated)').each(function () {
  197. new IHKExtendedSearch($(this));
  198. });
  199. });