qsearch.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /**
  2. * AJAX functions for the pagename quicksearch
  3. *
  4. * @license GPL2 (http://www.gnu.org/licenses/gpl.html)
  5. * @author Andreas Gohr <andi@splitbrain.org>
  6. * @author Adrian Lang <lang@cosmocode.de>
  7. * @author Michal Rezler <m.rezler@centrum.cz>
  8. */
  9. jQuery.fn.dw_qsearch = function (overrides) {
  10. var dw_qsearch = {
  11. output: '#qsearch__out',
  12. $inObj: this,
  13. $outObj: null,
  14. timer: null,
  15. curRequest: null,
  16. /**
  17. * initialize the quick search
  18. *
  19. * Attaches the event handlers
  20. *
  21. */
  22. init: function () {
  23. var do_qsearch;
  24. dw_qsearch.$outObj = jQuery(dw_qsearch.output);
  25. // objects found?
  26. if (dw_qsearch.$inObj.length === 0 ||
  27. dw_qsearch.$outObj.length === 0) {
  28. return;
  29. }
  30. // attach eventhandler to search field
  31. do_qsearch = function () {
  32. // abort any previous request
  33. if (dw_qsearch.curRequest != null) {
  34. dw_qsearch.curRequest.abort();
  35. }
  36. var value = dw_qsearch.getSearchterm();
  37. if (value === '') {
  38. dw_qsearch.clear_results();
  39. return;
  40. }
  41. dw_qsearch.$inObj.parents('form').addClass('searching');
  42. dw_qsearch.curRequest = jQuery.post(
  43. DOKU_BASE + 'lib/exe/ajax.php',
  44. {
  45. call: 'qsearch',
  46. q: encodeURI(value)
  47. },
  48. dw_qsearch.onCompletion,
  49. 'html'
  50. );
  51. };
  52. dw_qsearch.$inObj.on('keyup',
  53. function () {
  54. if (dw_qsearch.timer) {
  55. window.clearTimeout(dw_qsearch.timer);
  56. dw_qsearch.timer = null;
  57. }
  58. dw_qsearch.timer = window.setTimeout(do_qsearch, 500);
  59. }
  60. );
  61. // attach eventhandler to output field
  62. dw_qsearch.$outObj.on('click', dw_qsearch.clear_results);
  63. },
  64. /**
  65. * Read search term from input
  66. */
  67. getSearchterm: function() {
  68. return dw_qsearch.$inObj.val();
  69. },
  70. /**
  71. * Empty and hide the output div
  72. */
  73. clear_results: function () {
  74. dw_qsearch.$inObj.parents('form').removeClass('searching');
  75. dw_qsearch.$outObj.hide();
  76. dw_qsearch.$outObj.text('');
  77. },
  78. /**
  79. * Callback. Reformat and display the results.
  80. *
  81. * Namespaces are shortened here to keep the results from overflowing
  82. * or wrapping
  83. *
  84. * @param data The result HTML
  85. */
  86. onCompletion: function (data) {
  87. var max, $links, too_big;
  88. dw_qsearch.$inObj.parents('form').removeClass('searching');
  89. dw_qsearch.curRequest = null;
  90. if (data === '') {
  91. dw_qsearch.clear_results();
  92. return;
  93. }
  94. dw_qsearch.$outObj
  95. .html(data)
  96. .show()
  97. .css('white-space', 'nowrap');
  98. // disable overflow during shortening
  99. dw_qsearch.$outObj.find('li').css('overflow', 'visible');
  100. $links = dw_qsearch.$outObj.find('a');
  101. max = dw_qsearch.$outObj[0].clientWidth; // maximum width allowed (but take away paddings below)
  102. if (document.documentElement.dir === 'rtl') {
  103. max -= parseInt(dw_qsearch.$outObj.css('padding-left'));
  104. too_big = function (l) {
  105. return l.offsetLeft < 0;
  106. };
  107. } else {
  108. max -= parseInt(dw_qsearch.$outObj.css('padding-right'));
  109. too_big = function (l) {
  110. return l.offsetWidth + l.offsetLeft > max;
  111. };
  112. }
  113. $links.each(function () {
  114. var start, length, replace, nsL, nsR, eli, runaway;
  115. if (!too_big(this)) {
  116. return;
  117. }
  118. nsL = this.textContent.indexOf('(');
  119. nsR = this.textContent.indexOf(')');
  120. eli = 0;
  121. runaway = 0;
  122. while ((nsR - nsL > 3) && too_big(this) && runaway++ < 500) {
  123. if (eli !== 0) {
  124. // elipsis already inserted
  125. if ((eli - nsL) > (nsR - eli)) {
  126. // cut left
  127. start = eli - 2;
  128. length = 2;
  129. } else {
  130. // cut right
  131. start = eli + 1;
  132. length = 1;
  133. }
  134. replace = '';
  135. } else {
  136. // replace middle with ellipsis
  137. start = Math.floor(nsL + ((nsR - nsL) / 2));
  138. length = 1;
  139. replace = '…';
  140. }
  141. this.textContent = substr_replace(this.textContent,
  142. replace, start, length);
  143. eli = this.textContent.indexOf('…');
  144. nsL = this.textContent.indexOf('(');
  145. nsR = this.textContent.indexOf(')');
  146. }
  147. });
  148. // reenable overflow
  149. dw_qsearch.$outObj.find('li').css('overflow', 'hidden').css('text-overflow', 'ellipsis');
  150. }
  151. };
  152. jQuery.extend(dw_qsearch, overrides);
  153. if (!overrides.deferInit) {
  154. dw_qsearch.init();
  155. }
  156. return dw_qsearch;
  157. };
  158. jQuery(function () {
  159. jQuery('#qsearch__in').dw_qsearch({
  160. output: '#qsearch__out'
  161. });
  162. });