autocomplete.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. layui.define(['jquery', 'laytpl', 'layer'], function (e) {
  2. "use strict";
  3. var hint = layui.hint(),
  4. $ = layui.jquery,
  5. laytpl = layui.laytpl,
  6. layer = layui.layer,
  7. module = 'autocomplete',
  8. filter = 'layui-autocomplete',
  9. container = 'layui-form-autocomplete',
  10. container_focus = 'layui-form-autocomplete-focus',
  11. system = {
  12. config: {
  13. template: ['<div class="layui-form-autocomplete">', '<dl class="layui-anim layui-anim-upbit">', '</dl>', '</div>'].join(''),
  14. layout: ['<dd data-index="{{d.index}}">{{- d.text}}</dd>'].join(''),
  15. template_txt: '{{d.text}}',
  16. template_val: '{{d.value}}',
  17. cache: false
  18. },
  19. data: {}
  20. },
  21. callback = function () {
  22. var _self = this,
  23. _config = _self.config;
  24. return {
  25. call: function (handle, params) {
  26. if (!_self.handles[handle]) return hint.error(handle + " handle is not defined");
  27. _self.handles[handle].call(_self, params)
  28. }
  29. }
  30. },
  31. job = function (e) {
  32. var _self = this;
  33. _self.config = $.extend({}, _self.config, system.config, e);
  34. _self.render();
  35. };
  36. job.prototype.config = {
  37. response: {
  38. code: 'code',
  39. data: 'content'
  40. },
  41. request: {
  42. keywords: 'keywords'
  43. },
  44. time_limit: 300,
  45. pullTimer: null,
  46. data: {},
  47. temp_data: {},
  48. params: {},
  49. filter: '',
  50. method: 'get',
  51. ajaxParams: {}
  52. }
  53. job.prototype.render = function () {
  54. var _self = this, _config = _self.config;
  55. if (_config.elem = $(_config.elem), _config.where = _config.where || {}, !_config.elem[0]) return _self;
  56. var _elem = _config.elem,
  57. _container = _elem.next('.' + container),
  58. _html = _self.elem = $(laytpl(_config.template).render({}));
  59. _config.id = _self.id, _container && _container.remove(), _elem.attr('autocomplete', 'off'), _elem.after(_html);
  60. _self.events()
  61. }
  62. job.prototype.pullData = function () {
  63. var _self = this,
  64. _config = _self.config,
  65. _elem = _config.elem,
  66. _container = _elem.next('.' + container);
  67. if (!_config.filter) return _self.renderData([]);
  68. if ((_config.cache || !_config.url) && Object.keys(_config.data).length > 0) return _self.renderData(_config.data);
  69. var keywords = _config.request.keywords
  70. var params = {
  71. t: new Date().getTime()
  72. }
  73. params[keywords] = _config.filter;
  74. var $loading = $('<i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i>');
  75. $.ajax($.extend({
  76. type: _config.method,
  77. url: _config.url,
  78. data: $.extend(params, _config.params instanceof Function ? _config.params() :_config.params),
  79. contentType: 'text/json,charset=utf-8',
  80. dataType: "json",
  81. beforeSend: function () {
  82. $loading.attr('style', [
  83. 'position:absolute',
  84. 'left:' + (_elem.offset().left + _elem.outerWidth() - 20) + 'px',
  85. 'top:' + _elem.offset().top + 'px',
  86. 'height:' + _elem.height() + 'px',
  87. 'line-height:' + _elem.height() + 'px'
  88. ].join(';'));
  89. $loading.appendTo('body');
  90. },
  91. success: function (resp) {
  92. $loading.remove();
  93. return 0 != resp[_config.response.code] ? layer.msg(resp[_config.response.data]) : _config.data = resp[_config.response.data], _self.renderData(_config.data)
  94. },
  95. error: function () {
  96. hint.error("请求失败")
  97. }
  98. }, _config.ajaxParams))
  99. }
  100. job.prototype.renderData = function (resp) {
  101. var _self = this,
  102. _config = _self.config,
  103. _elem = _config.elem,
  104. _container = _elem.next('.' + container),
  105. _dom = _container.find('dl'),
  106. _list = [];
  107. _config.temp_data = [];
  108. layui.each(resp, function (i, e) {
  109. if (_config.cache) {
  110. if (e instanceof Object) {
  111. layui.each(e, function (_i, _e) {
  112. if (_e.toString().toLowerCase().indexOf(_config.filter.toLowerCase()) > -1) {
  113. _config.temp_data.push(e), _list.push(laytpl(_config.layout).render({ index: i, text: laytpl(_config.template_txt).render(e) }));
  114. return true;
  115. }
  116. });
  117. } else {
  118. if (e.toString().toLowerCase().indexOf(_config.filter.toLowerCase()) > -1) {
  119. _config.temp_data.push(e), _list.push(laytpl(_config.layout).render({ index: i, text: laytpl(_config.template_txt).render(e) }));
  120. }
  121. }
  122. } else {
  123. _config.temp_data.push(e), _list.push(laytpl(_config.layout).render({ index: i, text: laytpl(_config.template_txt).render(e) }));
  124. }
  125. });
  126. _dom.html(_list.join('')), _list.length > 0 ? _container.addClass(container_focus) : _container.removeClass(container_focus)
  127. }
  128. job.prototype.handles = {
  129. addData: function (data) {
  130. var _self = this,
  131. _config = _self.config;
  132. if (data instanceof Array) {
  133. _config.data = _config.data.concat(data)
  134. } else {
  135. _config.data.push(data)
  136. }
  137. },
  138. setData: function (data) {
  139. var _self = this,
  140. _config = _self.config;
  141. _config.data = data;
  142. }
  143. }
  144. job.prototype.events = function () {
  145. var _self = this,
  146. _config = _self.config,
  147. _elem = _config.elem,
  148. _container = _elem.next('.' + container),
  149. _dom = _container.find('dl');
  150. _elem.unbind('focus').unbind('input propertychange').on('focus', function () {
  151. _config.filter = this.value, _self.renderData(_config.data)
  152. }).on('input propertychange', function (e) {
  153. var _value = this.value;
  154. clearTimeout(_config.pullTimer), _config.pullTimer = setTimeout(function () {
  155. _config.filter = _value, _self.pullData()
  156. }, _config.time_limit)
  157. })
  158. $(document).on('click', function (e) {
  159. var _target = e.target, _item = _dom.find(_target), _e = _item.length > 0 ? _item.closest('dd') : undefined;
  160. if (_target === _elem[0]) return false;
  161. if (_e !== undefined) {
  162. if (_e.attr('autocomplete-load') !== undefined) return false;
  163. var curr_data = _config.temp_data[_e.index()]
  164. _elem.val(laytpl(_config.template_val).render(curr_data)), _config.onselect == undefined || _config.onselect(curr_data)
  165. }
  166. _container.removeClass(container_focus);
  167. })
  168. }
  169. system.init = function (e, c) {
  170. var c = c || {}, _self = this, _elems = $(e ? 'input[lay-filter="' + e + '"]' : 'input[' + filter + ']');
  171. _elems.each(function (_i, _e) {
  172. var _elem = $(_e),
  173. _lay_data = _elem.attr('lay-data');
  174. try {
  175. _lay_data = new Function("return " + _lay_data)()
  176. } catch (ex) {
  177. return hint.error("autocomplete元素属性lay-data配置项存在语法错误:" + _lay_data)
  178. }
  179. var _config = $.extend({ elem: this }, system.config, c, _lay_data);
  180. _config.url == undefined && (_config.data == undefined || _config.length === 0) && hint.error("autocomplete配置有误,缺少获取数据方式");
  181. system.render(_config);
  182. })
  183. }
  184. system.render = function (e) {
  185. var j = new job(e);
  186. return callback.call(j)
  187. }
  188. system.init(), e(module, system);
  189. });