No Description

typeahead.js 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. $.use(["jQuery", "form", "doc", "util", "dropdown", "code"], function($, form, doc, util, dd, code) {
  2. var m_rd = "必选的",
  3. modelName = 'typeahead',
  4. placeholder = "placeholder",
  5. required = "required",
  6. typeahead = function() {
  7. this.ve = null;
  8. this.minLength = 1;
  9. this.maxShowCount = 10;
  10. this.keyPressInterval = 500;
  11. this.caption = "";
  12. this.autoselect = true;
  13. this.ajaxCfg={mask:false};
  14. };
  15. typeahead.prototype = defCfg = {};
  16. defCfg.source = function(query, hand) {
  17. // console.log("source:" + query)
  18. var self = this;
  19. this.lastQuerying = query;
  20. setTimeout(function() {
  21. if((query === self.lastQuerying) && (query !== self.lastQueryed)) {
  22. self.doQuery(query, hand);
  23. }
  24. }, this.keyPressInterval || 500);
  25. };
  26. defCfg.doQuery = function(query, hand) {
  27. var self = this;
  28. this.lastQueryed = query;
  29. // console.log("doQuery:" + query);
  30. util.get(this.quri + encodeURIComponent(query), null, function(data) {
  31. if(self.lastQueryed === query) {
  32. if(self.transfer) {
  33. data = self.transfer(data);
  34. }
  35. // console.log("doHand:" + query);
  36. hand(data);
  37. }
  38. }, this.ajaxEH, this.ajaxCfg);
  39. };
  40. defCfg.blur = function() {
  41. var self = this;
  42. setTimeout(function() {
  43. self.hide();
  44. }, 150);
  45. };
  46. defCfg.keydown = function(e) {
  47. this.suppressKeyPressRepeat = [40, 38, 9, 13, 27].indexOf(e.keyCode) >= 0;
  48. this.move(e);
  49. };
  50. defCfg.move = function(e) {
  51. if(!this.shown) return;
  52. switch(e.keyCode) {
  53. case 9: // tab
  54. case 13: // enter
  55. case 27: // escape
  56. e.preventDefault();
  57. break;
  58. case 38: // up arrow
  59. e.preventDefault();
  60. this.prev();
  61. break;
  62. case 40: // down arrow
  63. e.preventDefault();
  64. this.next();
  65. break;
  66. }
  67. e.stopPropagation();
  68. };
  69. defCfg.keypress = function(e) {
  70. if(this.suppressKeyPressRepeat) return;
  71. this.move(e);
  72. };
  73. defCfg.keyup = function(e) {
  74. var self = this;
  75. switch(e.keyCode) {
  76. case 40: // down arrow
  77. case 38: // up arrow
  78. break;
  79. case 9: // tab
  80. case 13: // enter
  81. if(!self.shown) return;
  82. self.select();
  83. break;
  84. case 27: // escape
  85. if(!self.shown) return;
  86. self.hide();
  87. break;
  88. default:
  89. self.lookup();
  90. }
  91. e.stopPropagation();
  92. e.preventDefault();
  93. };
  94. defCfg.click = function(e) {
  95. e.stopPropagation();
  96. e.preventDefault();
  97. this.select();
  98. };
  99. defCfg.mouseenter = function(e) {
  100. this.ctn.find('.active').removeClass('active');
  101. $(e.currentTarget).addClass('active');
  102. };
  103. defCfg.prev = function(e) {
  104. var active = this.ctn.find('.active').removeClass('active');
  105. var prev = active.prev();
  106. if(!prev.length) {
  107. prev = this.ctn.find('li').last();
  108. }
  109. prev.addClass('active');
  110. };
  111. defCfg.next = function(e) {
  112. var active = this.ctn.find('.active').removeClass('active');
  113. var next = active.next();
  114. if(!next.length) {
  115. next = this.ctn.find('li').first();
  116. }
  117. next.addClass('active');
  118. };
  119. defCfg.render = function(items) {
  120. var lis = [];
  121. items.forEach(function(item) {
  122. var pc = String(item.code || item);
  123. var pt = String(item.caption || item);
  124. lis.push({
  125. tn: "li",
  126. attrs: [{
  127. an: "code",
  128. av: pc
  129. }, {
  130. an: "caption",
  131. av: pt
  132. }, {
  133. an: "class",
  134. av: "select-item"
  135. }],
  136. chs: [pt]
  137. });
  138. });
  139. if(this.autoselect && lis.length) {
  140. lis[0].attrs[2].av = " active select-item";
  141. }
  142. this.menu.empty();
  143. util.appendChild(this.menu[0], lis);
  144. return this;
  145. };
  146. defCfg.lookup = function(event) {
  147. var self = this;
  148. self.query = self.ve.val();
  149. if(!self.query || self.query.length < self.minLength) {
  150. return self.shown ? self.hide() : self
  151. }
  152. if(self.source instanceof Function) {
  153. self.source(self.query, function() {
  154. self.process.apply(self, arguments);
  155. });
  156. } else {
  157. self.process(self.source);
  158. }
  159. return self;
  160. };
  161. defCfg.process = function(items) {
  162. if(items && items.length) {
  163. this.render(items.slice(0, this.maxShowCount));
  164. this.show();
  165. }
  166. };
  167. defCfg.show = function() {
  168. this.shown = true;
  169. this.ctn.addClass("open");
  170. };
  171. defCfg.hide = function() {
  172. this.shown = false;
  173. this.ctn.removeClass("open");
  174. var v = this.ve.val();
  175. if(v) {
  176. if(v !== this.caption) {
  177. this.ve.val(this.caption);
  178. }
  179. } else {
  180. this.rv = "";
  181. this.caption = "";
  182. }
  183. this.lastQuerying = null;
  184. this.lastQueryed = null;
  185. };
  186. defCfg.select = function() {
  187. if(this.shown) {
  188. var item = this.menu.find(".active");
  189. this.rv = item.attr('code');
  190. this.caption = item.attr("caption");
  191. this.ve.val(this.caption);
  192. return this.hide();
  193. }
  194. };
  195. defCfg.init = function($e) {
  196. var self = this;
  197. this.ctn = $e;
  198. var ve = $e.children(".dd-drop");
  199. if(ve.length && ve.children("ul").length === 1) {
  200. var rc = code.parseCode(ve);
  201. rc.empty();
  202. this.render = function(items) {
  203. rc.val(items);
  204. self.menu=self.ctn.find(".dd-drop>ul");
  205. }
  206. } else {
  207. $("<div class='dd-drop'><ul></ul></div>").appendTo($e);
  208. }
  209. this.menu = $e.find(".dd-drop>ul");
  210. ve = this.ve = $("<input type='text'/>");
  211. var tmp = $e.attr(placeholder);
  212. if(tmp) ve.attr(placeholder, tmp);
  213. $e.addClass("dd-ctn").append(ve).removeClass("dd-clean");
  214. this.shown = false;
  215. this.quri = this.quri || $e.attr("uri");
  216. this.minLength == this.minLength || parseInt($e.attr("minQueryLen") || "1");
  217. this.maxShowCount = this.maxShowCount || parseInt($e.attr("minQueryLen") || "1");
  218. this.keyPressInterval = this.keyPressInterval || parseInt($e.attr("keyPressInterval") || "500");
  219. ve.on("blur", function(e) {
  220. self.blur(e);
  221. });
  222. ve.on("keypress", function(e) {
  223. self.keypress(e);
  224. });
  225. ve.on("keyup", function(e) {
  226. self.keyup(e);
  227. });
  228. ve.on("keydown", function(e) {
  229. self.keydown(e);
  230. });
  231. $e.children(".dd-drop").on("click", function(e) {
  232. self.click(e);
  233. });
  234. $e.children(".dd-drop").on("mouseenter", "li", function(e) {
  235. self.mouseenter(e);
  236. });
  237. };
  238. form.register(function($e, options) {
  239. var cls = util.classCheck($e[0], [modelName, required]),
  240. config;
  241. if(cls[modelName]) {
  242. var n = $e.attr("name") || $e.attr("id"),
  243. ve, rules = [];
  244. if(!n) {
  245. throw "Attribute[name] is invalid";
  246. }
  247. config = $.extend(new typeahead(), options ? options[n] || {} : {});
  248. config.dv = $e.attr("defVal") || "";
  249. config.rv = config.dv;
  250. if(!config.rules) {
  251. config.rules = [];
  252. }
  253. config.init($e);
  254. return {
  255. name: n,
  256. get: function() {
  257. return config.rv;
  258. },
  259. set: function(data) {
  260. config.rv = data;
  261. },
  262. validate: function() {
  263. if(cls[required]) {
  264. if(!config.rv) {
  265. this.invalid(m_rd);
  266. return m_rd;
  267. }
  268. }
  269. return util.validate(config.rules, this);
  270. },
  271. addRules: function(rule) {
  272. util.addRules(config.rules, rule);
  273. },
  274. reset: function() {
  275. this.set(dv);
  276. },
  277. valid: function() {
  278. util.valid($e);
  279. },
  280. invalid: function(reson) {
  281. util.invalid($e);
  282. util.error(reson);
  283. }
  284. };
  285. }
  286. });
  287. });