search.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * Fuel UX Search
  3. * https://github.com/ExactTarget/fuelux
  4. *
  5. * Copyright (c) 2014 ExactTarget
  6. * Licensed under the BSD New license.
  7. */
  8. // -- BEGIN UMD WRAPPER PREFACE --
  9. // For more information on UMD visit:
  10. // https://github.com/umdjs/umd/blob/master/jqueryPlugin.js
  11. (function (factory) {
  12. if (typeof define === 'function' && define.amd) {
  13. // if AMD loader is available, register as an anonymous module.
  14. define(['jquery'], factory);
  15. } else {
  16. // OR use browser globals if AMD is not present
  17. factory(jQuery);
  18. }
  19. }(function ($) {
  20. // -- END UMD WRAPPER PREFACE --
  21. // -- BEGIN MODULE CODE HERE --
  22. var old = $.fn.search;
  23. // SEARCH CONSTRUCTOR AND PROTOTYPE
  24. var Search = function (element, options) {
  25. this.$element = $(element);
  26. this.options = $.extend({}, $.fn.search.defaults, options);
  27. this.$button = this.$element.find('button');
  28. this.$input = this.$element.find('input');
  29. this.$icon = this.$element.find('.glyphicon');
  30. this.$button.on('click.fu.search', $.proxy(this.buttonclicked, this));
  31. this.$input.on('keydown.fu.search', $.proxy(this.keypress, this));
  32. this.$input.on('keyup.fu.search', $.proxy(this.keypressed, this));
  33. this.activeSearch = '';
  34. };
  35. Search.prototype = {
  36. constructor: Search,
  37. destroy: function () {
  38. this.$element.remove();
  39. // any external bindings
  40. // [none]
  41. // set input value attrbute
  42. this.$element.find('input').each(function () {
  43. $(this).attr('value', $(this).val());
  44. });
  45. // empty elements to return to original markup
  46. // [none]
  47. // returns string of markup
  48. return this.$element[0].outerHTML;
  49. },
  50. search: function (searchText) {
  51. if (this.$icon.hasClass('glyphicon')) {
  52. this.$icon.removeClass('glyphicon-search').addClass('glyphicon-remove');
  53. }
  54. this.activeSearch = searchText;
  55. this.$element.addClass('searched');
  56. this.$element.trigger('searched.fu.search', searchText);
  57. },
  58. clear: function () {
  59. if (this.$icon.hasClass('glyphicon')) {
  60. this.$icon.removeClass('glyphicon-remove').addClass('glyphicon-search');
  61. }
  62. this.activeSearch = '';
  63. this.$input.val('');
  64. this.$element.removeClass('searched');
  65. this.$element.trigger('cleared.fu.search');
  66. },
  67. action: function () {
  68. var val = this.$input.val();
  69. var inputEmptyOrUnchanged = (val === '' || val === this.activeSearch);
  70. if (this.activeSearch && inputEmptyOrUnchanged) {
  71. this.clear();
  72. } else if (val) {
  73. this.search(val);
  74. }
  75. },
  76. buttonclicked: function (e) {
  77. e.preventDefault();
  78. if ($(e.currentTarget).is('.disabled, :disabled')) return;
  79. this.action();
  80. },
  81. keypress: function (e) {
  82. if (e.which === 13) {
  83. e.preventDefault();
  84. }
  85. },
  86. keypressed: function (e) {
  87. var remove = 'glyphicon-remove';
  88. var search = 'glyphicon-search';
  89. var val;
  90. if (e.which === 13) {
  91. e.preventDefault();
  92. this.action();
  93. } else if (e.which === 9) {
  94. e.preventDefault();
  95. } else {
  96. val = this.$input.val();
  97. if (val !== this.activeSearch || !val) {
  98. this.$icon.removeClass(remove).addClass(search);
  99. if (val) {
  100. this.$element.removeClass('searched');
  101. } else if (this.options.clearOnEmpty) {
  102. this.clear();
  103. }
  104. } else {
  105. this.$icon.removeClass(search).addClass(remove);
  106. }
  107. }
  108. },
  109. disable: function () {
  110. this.$element.addClass('disabled');
  111. this.$input.attr('disabled', 'disabled');
  112. this.$button.addClass('disabled');
  113. },
  114. enable: function () {
  115. this.$element.removeClass('disabled');
  116. this.$input.removeAttr('disabled');
  117. this.$button.removeClass('disabled');
  118. }
  119. };
  120. // SEARCH PLUGIN DEFINITION
  121. $.fn.search = function (option) {
  122. var args = Array.prototype.slice.call(arguments, 1);
  123. var methodReturn;
  124. var $set = this.each(function () {
  125. var $this = $(this);
  126. var data = $this.data('fu.search');
  127. var options = typeof option === 'object' && option;
  128. if (!data) {
  129. $this.data('fu.search', (data = new Search(this, options)));
  130. }
  131. if (typeof option === 'string') {
  132. methodReturn = data[option].apply(data, args);
  133. }
  134. });
  135. return (methodReturn === undefined) ? $set : methodReturn;
  136. };
  137. $.fn.search.defaults = {
  138. clearOnEmpty: false
  139. };
  140. $.fn.search.Constructor = Search;
  141. $.fn.search.noConflict = function () {
  142. $.fn.search = old;
  143. return this;
  144. };
  145. // DATA-API
  146. $(document).on('mousedown.fu.search.data-api', '[data-initialize=search]', function (e) {
  147. var $control = $(e.target).closest('.search');
  148. if (!$control.data('fu.search')) {
  149. $control.search($control.data());
  150. }
  151. });
  152. // Must be domReady for AMD compatibility
  153. $(function () {
  154. $('[data-initialize=search]').each(function () {
  155. var $this = $(this);
  156. if ($this.data('fu.search')) return;
  157. $this.search($this.data());
  158. });
  159. });
  160. // -- BEGIN UMD WRAPPER AFTERWORD --
  161. }));
  162. // -- END UMD WRAPPER AFTERWORD --