frontend.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. (function($) {
  2. FLBuilderSearchForm = function(settings) {
  3. this.settings = settings;
  4. this.nodeClass = '.fl-node-' + settings.id;
  5. this.searchForm = $(this.nodeClass + ' .fl-search-form');
  6. this.form = this.searchForm.find('form');
  7. this.input = this.form.find('input[type=search]');
  8. this.button = this.searchForm.find('a.fl-button, a.fl-button *');
  9. this.resultsEl = $(this.nodeClass + ' .fl-search-results-content');
  10. this._init();
  11. };
  12. FLBuilderSearchForm.prototype = {
  13. settings: {},
  14. nodeClass: '',
  15. searchForm: '',
  16. form: null,
  17. input: null,
  18. button: null,
  19. resultsEl: '',
  20. searching: false,
  21. prevSearchData: {},
  22. request: null,
  23. _init: function() {
  24. this._bindEvents();
  25. this._popupSearch();
  26. },
  27. _bindEvents: function(){
  28. var $this = this,
  29. keyCode = null,
  30. keyType = null,
  31. enterPressed = false,
  32. t, et;
  33. this.button.on('click', $.proxy(this._buttonClick, this));
  34. if ( 'ajax' == this.settings.result ) {
  35. $(document).on('click touchend', function(e){
  36. if( $(e.target).is('input') ) return;
  37. $this._hideResults();
  38. } );
  39. $this.resultsEl.bind("click touchend", function (e) {
  40. e.stopImmediatePropagation();
  41. });
  42. // Disable form submit.
  43. $this.form.on( 'submit', function (e) {
  44. e.preventDefault();
  45. });
  46. this.input.on('keyup', function(e) {
  47. if (window.event) {
  48. keyCode = window.event.keyCode;
  49. keyType = window.event.type;
  50. } else if (e) {
  51. keyCode = e.which;
  52. keyType = e.type;
  53. }
  54. // Prevent rapid enter
  55. if ( 13 == keyCode ) {
  56. clearTimeout(et);
  57. et = setTimeout(function(){
  58. enterPressed = false;
  59. }, 300);
  60. if ( enterPressed ) {
  61. return false;
  62. } else {
  63. enterPressed = true;
  64. }
  65. }
  66. if ( $this.input.val().length >= 3 && 'keyup' == keyType && 13 == keyCode ) {
  67. $this._search(e);
  68. return false;
  69. }
  70. });
  71. this.input.on('click input', function(e) {
  72. if (window.event) {
  73. keyCode = window.event.keyCode;
  74. keyType = window.event.type;
  75. } else if (e) {
  76. keyCode = e.which;
  77. keyType = e.type;
  78. }
  79. // F1 to F12
  80. if ( (keyCode >= 37 && keyCode <= 40) || (keyCode >= 112 && keyCode <= 123) ) {
  81. return;
  82. }
  83. if ($this.input.val().length < 3) {
  84. $this._hideLoader();
  85. $this._hideResults();
  86. if ($this.post != null) $this.post.abort();
  87. clearTimeout(t);
  88. return;
  89. }
  90. if ( 'click' == keyType || keyCode == 32 ) {
  91. if ( $this.resultsEl.html().length != 0 ) {
  92. clearTimeout(t);
  93. if( $this.resultsEl.hasClass('fl-search-open') ) return;
  94. $this._showResults();
  95. }
  96. else {
  97. $this._hideResults();
  98. }
  99. return;
  100. }
  101. if ($this.request != null) $this.request.abort();
  102. $this._hideLoader();
  103. clearTimeout(t);
  104. t = setTimeout(function() {
  105. $this._search(e);
  106. }, 100);
  107. });
  108. }
  109. },
  110. _search: function(e) {
  111. e.preventDefault();
  112. if ($.trim(this.input.val()).length < 1) {
  113. return;
  114. }
  115. if ( 'ajax' == this.settings.result ) {
  116. this._doAjaxSearch();
  117. }
  118. else {
  119. this.form.submit();
  120. // TODO: _doRedirectResults()
  121. }
  122. return false;
  123. },
  124. _doAjaxSearch: function() {
  125. var searchText = this.input.val(),
  126. postId = this.searchForm.closest( '.fl-builder-content' ).data( 'post-id' ),
  127. templateId = this.searchForm.data( 'template-id' ),
  128. templateNodeId = this.searchForm.data( 'template-node-id' ),
  129. ajaxData = {},
  130. self = this;
  131. if ( this.searching && 0 ) return;
  132. if ( searchText.length < 1 ) return;
  133. this.searching = true;
  134. // Show loader
  135. this._showLoader();
  136. ajaxData = {
  137. action : 'fl_search_query',
  138. keyword : searchText,
  139. post_id : postId,
  140. template_id : templateId,
  141. template_node_id : templateNodeId,
  142. node_id : this.settings.id,
  143. }
  144. // Check to see if searching the same keywords.
  145. if ( JSON.stringify(ajaxData) === JSON.stringify(this.prevSearchData) ) {
  146. if ( ! this.resultsEl.hasClass('fl-search-open') ) {
  147. this._showResults();
  148. }
  149. this._hideLoader();
  150. return false;
  151. }
  152. // Send server request.
  153. this.request = $.post( FLBuilderLayoutConfig.paths.wpAjaxUrl, ajaxData, function(response){
  154. self._hideLoader();
  155. self.resultsEl.html("");
  156. self.resultsEl.html(response);
  157. self._showResults();
  158. self.prevSearchData = ajaxData;
  159. });
  160. },
  161. _popupSearch: function() {
  162. var inputWrap = this.searchForm.find('.fl-search-form-input-wrap'),
  163. $this = this;
  164. if ('button' != this.settings.layout || 'fullscreen' != this.settings.btnAction) {
  165. return;
  166. }
  167. this.button.off('click');
  168. this.button.magnificPopup({
  169. type: 'inline',
  170. mainClass: 'fl-node-' + this.settings.id,
  171. items: {
  172. src: inputWrap[0],
  173. },
  174. alignTop: true,
  175. showCloseBtn: $this.settings.showCloseBtn,
  176. closeBtnInside: false,
  177. enableEscapeKey: true,
  178. closeOnBgClick: false,
  179. focus: 'input[type=search]',
  180. tLoading: '<i class="fas fa-spinner fa-spin fa-3x fa-fw"></i>',
  181. callbacks: {
  182. open: function(){
  183. $this.input.trigger('click');
  184. }
  185. }
  186. });
  187. this.resultsEl.appendTo( inputWrap );
  188. },
  189. _buttonClick: function(e) {
  190. e.stopImmediatePropagation();
  191. if (this.searchForm.hasClass('fl-search-button-expand')) {
  192. this.searchForm.find('.fl-search-form-wrap').toggleClass('fl-search-expanded');
  193. if (this.searchForm.find('.fl-search-form-wrap').hasClass('fl-search-expanded')) {
  194. this.input.focus();
  195. }
  196. else {
  197. this._hideResults();
  198. }
  199. return false;
  200. } else {
  201. this._search(e);
  202. }
  203. },
  204. _showResults: function(){
  205. // Close any search results in a page.
  206. this._hideResults();
  207. this.resultsEl.addClass('fl-search-open');
  208. if ('button' == this.settings.layout && 'expand' == this.settings.btnAction) {
  209. this.searchForm.find('.fl-search-form-input-wrap').css('overflow', 'visible');
  210. }
  211. },
  212. _hideResults: function(){
  213. $('.fl-search-results-content').removeClass('fl-search-open');
  214. if ('button' == this.settings.layout && 'expand' == this.settings.btnAction) {
  215. this.searchForm.find('.fl-search-form-input-wrap').removeAttr('style');
  216. }
  217. },
  218. _doRedirectResults: function(){
  219. // TODO
  220. },
  221. _showLoader: function(){
  222. $(this.nodeClass + ' .fl-search-loader-wrap').show();
  223. },
  224. _hideLoader: function(){
  225. this.searching = false;
  226. $(this.nodeClass + ' .fl-search-loader-wrap').hide();
  227. },
  228. _cleanInput: function(s) {
  229. return encodeURIComponent(s).replace(/\%20/g, '+');
  230. }
  231. }
  232. })(jQuery);