input-autocomplete.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*!
  2. input-autocomplete v1.0
  3. @author: starIl
  4. */
  5. (function($){
  6. var bigAutocomplete = new function(){
  7. this.currentInputText = null;//目前获得光标的输入框(解决一个页面多个输入框绑定自动补全功能)
  8. this.functionalKeyArray = [9,20,13,16,17,18,91,92,93,45,36,33,34,35,37,39,112,113,114,115,116,117,118,119,120,121,122,123,144,19,145,40,38,27];//键盘上功能键键值数组
  9. this.holdText = null;//输入框中原始输入的内容
  10. //初始化插入自动补全div,并在document注册mousedown,点击非div区域隐藏div
  11. this.init = function(){
  12. $("body").append("<div id='bigAutocompleteContent' class='bigautocomplete-layout'></div>");
  13. $(document).bind('mousedown',function(event){
  14. var $target = $(event.target);
  15. if((!($target.parents().andSelf().is('#bigAutocompleteContent'))) && (!$target.is(bigAutocomplete.currentInputText))){
  16. bigAutocomplete.hideAutocomplete();
  17. }
  18. })
  19. //鼠标悬停时选中当前行
  20. $("#bigAutocompleteContent").delegate("tr", "mouseover", function() {
  21. $("#bigAutocompleteContent tr").removeClass("ct");
  22. $(this).addClass("ct");
  23. }).delegate("tr", "mouseout", function() {
  24. $("#bigAutocompleteContent tr").removeClass("ct");
  25. });
  26. //单击选中行后,选中行内容设置到输入框中,并执行callback函数
  27. $("#bigAutocompleteContent").delegate("tr", "click", function() {
  28. var val = $(this).find("div:first").html();
  29. $(this).data("config",val);
  30. bigAutocomplete.currentInputText.data("customVal",val);
  31. bigAutocomplete.currentInputText.val(val);
  32. var callback_ = bigAutocomplete.currentInputText.data("config").callback;
  33. if($("#bigAutocompleteContent").css("display") != "none" && callback_ && $.isFunction(callback_)){
  34. callback_($(this).data("jsonData"),bigAutocomplete.currentInputText.data("config").param);
  35. }
  36. bigAutocomplete.hideAutocomplete();
  37. })
  38. }
  39. this.autocomplete = function(param){
  40. var $this = $(this);//为绑定自动补全功能的输入框jquery对象
  41. if($("body").length > 0 && $("#bigAutocompleteContent").length <= 0){
  42. bigAutocomplete.init($this);//初始化信息
  43. }
  44. var $bigAutocompleteContent = $("#bigAutocompleteContent");
  45. this.config = {
  46. /*
  47. * type : Number [可选]
  48. * width:下拉框的宽度,默认使用输入框宽度
  49. */
  50. width:$this.outerWidth() - 2,
  51. /*
  52. * type: Array
  53. * url和data参数只有一个生效,data优先
  54. */
  55. data:null,
  56. /*
  57. * type : String
  58. * url:格式url:""用来ajax后台获取数据,返回的数据格式为data参数一样
  59. * (自动取输入框的值,keyword:value)
  60. */
  61. url:null,
  62. /*
  63. * type : Boolean [可选]
  64. * 用户是否可以自定义值(false后只能单击或Enter能选中值)
  65. * =false时 清空全部值会调用callback方法 (null,param)
  66. */
  67. custom:true,
  68. /*
  69. * type : Function [可选]
  70. * 下拉框行格式化
  71. * params[(data,index,row)]
  72. */
  73. formatItem:null,
  74. /*
  75. * type : Function [可选]
  76. * 选中后输入框显示值 default : formatItem
  77. * params[(data,index,row)]
  78. */
  79. formatSelected:null,
  80. /*
  81. * type : String [可选]
  82. * default : title
  83. * 格式化输出后,选中值
  84. */
  85. title:'title',
  86. /*
  87. * type : Function [可选]
  88. * callback:选中行后按回车或单击时回调的函数
  89. * params[(row,param)]
  90. */
  91. callback:null,
  92. /*
  93. * [可选]
  94. * callback方法的第二个参数,用于自定义值
  95. */
  96. param:null,
  97. };
  98. $this.attr("title","单击或输入值匹配");
  99. $.extend(this.config,param);
  100. $this.data("config",this.config);
  101. $this.data("customVal",$.trim($this.val()));
  102. //输入框keydown事件
  103. $this.keydown(function(event) {
  104. switch (event.keyCode) {
  105. case 40://向下键
  106. if($bigAutocompleteContent.css("display") == "none")return;
  107. var $nextSiblingTr = $bigAutocompleteContent.find(".ct");
  108. if($nextSiblingTr.length <= 0){//没有选中行时,选中第一行
  109. $nextSiblingTr = $bigAutocompleteContent.find("tr:first");
  110. }else{
  111. $nextSiblingTr = $nextSiblingTr.next();
  112. }
  113. $bigAutocompleteContent.find("tr").removeClass("ct");
  114. if($nextSiblingTr.length > 0){//有下一行时(不是最后一行)
  115. $nextSiblingTr.addClass("ct");//选中的行加背景
  116. //div滚动到选中的行,jquery-1.6.1 $nextSiblingTr.offset().top 有bug,数值有问题
  117. $bigAutocompleteContent.scrollTop($nextSiblingTr[0].offsetTop - $bigAutocompleteContent.height() + $nextSiblingTr.height() );
  118. }
  119. break;
  120. case 38://向上键
  121. if($bigAutocompleteContent.css("display") == "none")return;
  122. var $previousSiblingTr = $bigAutocompleteContent.find(".ct");
  123. if($previousSiblingTr.length <= 0){//没有选中行时,选中最后一行行
  124. $previousSiblingTr = $bigAutocompleteContent.find("tr:last");
  125. }else{
  126. $previousSiblingTr = $previousSiblingTr.prev();
  127. }
  128. $bigAutocompleteContent.find("tr").removeClass("ct");
  129. if($previousSiblingTr.length > 0){//有上一行时(不是第一行)
  130. $previousSiblingTr.addClass("ct");//选中的行加背景
  131. //div滚动到选中的行,jquery-1.6.1 $$previousSiblingTr.offset().top 有bug,数值有问题
  132. $bigAutocompleteContent.scrollTop($previousSiblingTr[0].offsetTop - $bigAutocompleteContent.height() + $previousSiblingTr.height());
  133. }
  134. break;
  135. case 27://ESC键隐藏下拉框
  136. bigAutocomplete.hideAutocomplete();
  137. break;
  138. }
  139. });
  140. //输入框focus事件(查询全部值)
  141. $this.focus(function(){
  142. autocompleteSelect();
  143. }),
  144. //输入框keyup事件
  145. $this.keyup(function(event) {
  146. var k = event.keyCode;
  147. var ctrl = event.ctrlKey;
  148. var isFunctionalKey = false;//按下的键是否是功能键
  149. for(var i=0;i<bigAutocomplete.functionalKeyArray.length;i++){
  150. if(k == bigAutocomplete.functionalKeyArray[i]){
  151. isFunctionalKey = true;
  152. break;
  153. }
  154. }
  155. //k键值不是功能键或是ctrl+c、ctrl+x时才触发自动补全功能
  156. if(!isFunctionalKey && (!ctrl || (ctrl && k == 67) || (ctrl && k == 88)) ){
  157. autocompleteSelect();
  158. }
  159. //回车键
  160. if(k == 13){
  161. var callback_ = $this.data("config").callback;
  162. if($bigAutocompleteContent.css("display") != "none"){
  163. var $previousSiblingTr = $bigAutocompleteContent.find(".ct");
  164. //回车键 入值
  165. if($previousSiblingTr.length <= 0){//没有选中行时,选中第一行
  166. $previousSiblingTr = $bigAutocompleteContent.find("tr:first");
  167. }
  168. var val = $previousSiblingTr.find("div:first").html();
  169. $this.data("customVal",val);
  170. $this.val(val);//选中行内容设置到输入框中
  171. //回调方法
  172. if(callback_ && $.isFunction(callback_)){
  173. callback_($previousSiblingTr.data("jsonData"),$this.data("config").param);
  174. }
  175. $bigAutocompleteContent.hide();
  176. }
  177. }
  178. });
  179. //自动补全,查询
  180. function autocompleteSelect(){
  181. var config = $this.data("config");
  182. var offset = $this.offset();
  183. $bigAutocompleteContent.width(config.width);
  184. var h = $this.outerHeight() - 1;
  185. $bigAutocompleteContent.css({"top":offset.top + h,"left":offset.left});
  186. var data = config.data;
  187. var url = config.url;
  188. var title = config.title;
  189. var keyword_ = $.trim($this.val());
  190. if(data != null && $.isArray(data) ){
  191. /*
  192. var data_ = new Array();
  193. for(var i=0;i<data.length;i++){
  194. if(data[i][title] && data[i][title].toUpperCase().indexOf(keyword_.toUpperCase()) > -1){
  195. data_.push(data[i]);
  196. }
  197. }
  198. makeContAndShow(data_);
  199. */
  200. makeContAndShow(data);
  201. }else if(url != null && url != ""){//ajax请求数据
  202. //encodeURI 转换编码
  203. $.post(url,{keyword:keyword_},function(result){
  204. makeContAndShow(result.data)
  205. },"json")
  206. }
  207. bigAutocomplete.holdText = $this.val();
  208. }
  209. //组装下拉框html内容并显示
  210. function makeContAndShow(data_){
  211. if(data_ == null || data_.length <=0 ) return;
  212. var config = $this.data("config");
  213. var title = config.title;
  214. var cont = "<table><tbody>";
  215. if(config.formatItem == null){
  216. //默认格式
  217. for(var i=0;i<data_.length;i++){
  218. cont += "<tr><td><div style='display:none'>"+data_[i][title]+"</div><div>" + data_[i][title]+ "</div></td></tr>"
  219. }
  220. }else{
  221. //选中方法不存在时,优先
  222. config.formatSelected = config.formatSelected ? config.formatSelected : config.formatItem;
  223. //格式化
  224. for(var i=0;i<data_.length;i++){
  225. cont += "<tr><td><div style='display:none'>"+config.formatSelected(data_,i,data_[i])+"</div><div>" + config.formatItem(data_,i,data_[i]) + "</div></td></tr>"
  226. }
  227. }
  228. cont += "</tbody></table>";
  229. $bigAutocompleteContent.html(cont);
  230. $bigAutocompleteContent.show();
  231. //每行tr绑定数据,返回给回调函数
  232. $bigAutocompleteContent.find("tr").each(function(index){
  233. $(this).data("jsonData",data_[index]);
  234. })
  235. }
  236. //输入框blur事件
  237. $this.blur(function(){
  238. var config = $this.data("config");
  239. var callback_ = config.callback;
  240. var data = config.data;
  241. var url = config.url;
  242. var title = config.title;
  243. var keyword_ = $.trim($this.val());
  244. if(config.custom == false){//强制选取值
  245. //如果用户输入值与数据源不匹配,就恢复到原来的值
  246. if($this.data("customVal") != $this.val() && $this.val() != ''){
  247. var custom = true;//不匹配
  248. if(data != null && $.isArray(data) ){
  249. var data_ = new Array();
  250. for(var i=0;i<data.length;i++){
  251. if(data[i][title] == keyword_){
  252. if(callback_ && $.isFunction(callback_)){
  253. custom = false;//匹配到了
  254. $this.data("customVal",keyword_);
  255. callback_(data[i],config.param);
  256. }
  257. }
  258. }
  259. makeContAndShow(data_);
  260. }else if(url != null && url != ""){
  261. $.post(url,{keyword:encodeURI(encodeURI(keyword_))},function(result){
  262. for(var i=0;i<result.data.length;i++){
  263. if(result.data[i][title] == keyword_){
  264. if(callback_ && $.isFunction(callback_)){
  265. custom = false;//匹配到了
  266. $this.data("customVal",keyword_);
  267. callback_(result.data[i],config.param);
  268. }
  269. }
  270. }
  271. },"json")
  272. }
  273. //恢复原来值
  274. if(custom) $this.val($this.data("customVal"));
  275. }
  276. if($this.val() == ''){
  277. //回调方法
  278. if(callback_ && $.isFunction(callback_)){
  279. callback_(null,config.param);
  280. }
  281. }
  282. }else{
  283. //用户输入值后与列表直接匹配,光标移出后调用callback_ 方法
  284. if($this.data("customVal") != keyword_){
  285. if(data != null && $.isArray(data) ){
  286. var data_ = new Array();
  287. for(var i=0;i<data.length;i++){
  288. if(data[i][title] == keyword_){
  289. if(callback_ && $.isFunction(callback_)){
  290. $this.data("customVal",keyword_);
  291. callback_(data[i],config.param);
  292. }
  293. }
  294. }
  295. makeContAndShow(data_);
  296. }else if(url != null && url != ""){
  297. $.post(url,{keyword:encodeURI(encodeURI(keyword_))},function(result){
  298. for(var i=0;i<result.data.length;i++){
  299. if(result.data[i][title] == keyword_){
  300. if(callback_ && $.isFunction(callback_)){
  301. $this.data("customVal",keyword_);
  302. callback_(result.data[i],config.param);
  303. }
  304. }
  305. }
  306. },"json")
  307. }
  308. }
  309. }
  310. });
  311. //输入框focus事件
  312. $this.focus(function(){
  313. bigAutocomplete.currentInputText = $this;
  314. });
  315. }
  316. //隐藏下拉框
  317. this.hideAutocomplete = function(){
  318. var $bigAutocompleteContent = $("#bigAutocompleteContent");
  319. if($bigAutocompleteContent.css("display") != "none"){
  320. $bigAutocompleteContent.find("tr").removeClass("ct");
  321. $bigAutocompleteContent.hide();
  322. }
  323. }
  324. };
  325. $.fn.bigAutocomplete = bigAutocomplete.autocomplete;
  326. })(jQuery)