autocomplete

html文件:

1
<input id="theInput"type="text" autocomplete="off">
js文件:

1
this.initAutoComplete = function () { 2 $("#theInput").autocomplete({                        //将$("#theInput")绑上autocomplete 3 source: function (request, response) {                 //source 参数 4 $.ajax({ 5 type: 'post', 6 url: "/CustomAccount/GetADUsers", 7 dataType: "json", 8 data: { mail: request.term,isall:false }, //mail:request.term 传进去的是在#theInput中输入的值 9 success: function (data) { 10 response($.map(data, function (item) { 11 return { 12 displayname: item 13 }; 14 })); 15 } 16 }); 17 }, 18 select: function (event, ui) {         //select参数 19 $(this).val(ui.item.displayname); 20 return false; 21 }, 22 max: 10, 23 }).each(function () { 24 $(this).data("autocomplete")._renderItem = function (ul, item) { //重写了autocomplete里面的_renderItem函数 25 return $("<li>") 26 .data("item.autocomplete", item) 27 .append("<a data-type='autocomplete-item'>" + item.displayname + "</a>").attr('title', item.displayname) 28 .appendTo(ul); 29 }; 30 }); 31 };

前台js调用这个initAutoComplete 函数,利用ajax在controller里面取值,controller

 
   
CustomAccountController里面的GetADUsers方法:
1  [HttpPost]

2  public ActionResult GetADUsers(string mail, Boolean isall)

3 {

4   var results = this.systemUserService.FindADUsers(mail, isall);                           //return 一个list<String>,是根据传进来的mail值过滤的

5   results.AddRange(this.systemUserService.FindADGroups(mail, isall).Select(g => g.Email));//在原来的results里加上另一个根据传进来的mail值过滤的的List<> 
6
results.Sort(); //排序
7
return this.Json(results, JsonRequestBehavior.AllowGet);
8
}

 附件jQuery UI Autocomplete 1.9.1:

  1 /*!

  2  * jQuery UI Autocomplete 1.9.1

  3  * http://jqueryui.com

  4  *

  5  * Copyright 2012 jQuery Foundation and other contributors

  6  * Released under the MIT license.

  7  * http://jquery.org/license

  8  *

  9  * http://api.jqueryui.com/autocomplete/

 10  *

 11  * Depends:

 12  *    jquery.ui.core.js

 13  *    jquery.ui.widget.js

 14  *    jquery.ui.position.js

 15  *    jquery.ui.menu.js

 16  */

 17 (function ($, undefined) {

 18 

 19     // used to prevent race conditions with remote data sources

 20     var requestIndex = 0;

 21 

 22     $.widget("ui.autocomplete", {

 23         version: "1.9.1",

 24         defaultElement: "<input>",

 25         options: {

 26             appendTo: "body",

 27             autoFocus: false,

 28             delay: 300,

 29             minLength: 1,

 30             position: {

 31                 my: "left top",

 32                 at: "left bottom",

 33                 collision: "none"

 34             },

 35             source: null,            

 36             // callbacks

 37             change: null,

 38             close: null,

 39             focus: null,

 40             open: null,

 41             response: null,

 42             search: null,

 43             select: null,

 44             width: 0,

 45             max: 10,

 46 

 47         },

 48 

 49         pending: 0,

 50 

 51         _create: function () {

 52             // Some browsers only repeat keydown events, not keypress events,

 53             // so we use the suppressKeyPress flag to determine if we've already

 54             // handled the keydown event. #7269

 55             // Unfortunately the code for & in keypress is the same as the up arrow,

 56             // so we use the suppressKeyPressRepeat flag to avoid handling keypress

 57             // events when we know the keydown event was used to modify the

 58             // search term. #7799

 59             var suppressKeyPress, suppressKeyPressRepeat, suppressInput;

 60 

 61             this.isMultiLine = this._isMultiLine();

 62             this.valueMethod = this.element[this.element.is("input,textarea") ? "val" : "text"];

 63             this.isNewMenu = true;

 64 

 65             this.element

 66                 .addClass("ui-autocomplete-input")

 67                 .attr("autocomplete", "off");

 68 

 69             this._on(this.element, {

 70                 keydown: function (event) {

 71                     if (this.element.prop("readOnly")) {

 72                         suppressKeyPress = true;

 73                         suppressInput = true;

 74                         suppressKeyPressRepeat = true;

 75                         return;

 76                     }

 77 

 78                     suppressKeyPress = false;

 79                     suppressInput = false;

 80                     suppressKeyPressRepeat = false;

 81                     var keyCode = $.ui.keyCode;

 82                     switch (event.keyCode) {

 83                         case keyCode.PAGE_UP:

 84                             suppressKeyPress = true;

 85                             this._move("previousPage", event);

 86                             break;

 87                         case keyCode.PAGE_DOWN:

 88                             suppressKeyPress = true;

 89                             this._move("nextPage", event);

 90                             break;

 91                         case keyCode.UP:

 92                             suppressKeyPress = true;

 93                             this._keyEvent("previous", event);

 94                             break;

 95                         case keyCode.DOWN:

 96                             suppressKeyPress = true;

 97                             this._keyEvent("next", event);

 98                             break;

 99                         case keyCode.ENTER:

100                         case keyCode.NUMPAD_ENTER:

101                             // when menu is open and has focus

102                             if (this.menu.active) {

103                                 // #6055 - Opera still allows the keypress to occur

104                                 // which causes forms to submit

105                                 suppressKeyPress = true;

106                                 event.preventDefault();

107                                 this.menu.select(event);

108                             }

109                             break;

110                         case keyCode.TAB:

111                             if (this.menu.active) {

112                                 this.menu.select(event);

113                             }

114                             break;

115                         case keyCode.ESCAPE:

116                             if (this.menu.element.is(":visible")) {

117                                 this._value(this.term);

118                                 this.close(event);

119                                 // Different browsers have different default behavior for escape

120                                 // Single press can mean undo or clear

121                                 // Double press in IE means clear the whole form

122                                 event.preventDefault();

123                             }

124                             break;

125                         default:

126                             suppressKeyPressRepeat = true;

127                             // search timeout should be triggered before the input value is changed

128                             this._searchTimeout(event);

129                             break;

130                     }

131                 },

132                 keypress: function (event) {

133                     if (suppressKeyPress) {

134                         suppressKeyPress = false;

135                         event.preventDefault();

136                         return;

137                     }

138                     if (suppressKeyPressRepeat) {

139                         return;

140                     }

141 

142                     // replicate some key handlers to allow them to repeat in Firefox and Opera

143                     var keyCode = $.ui.keyCode;

144                     switch (event.keyCode) {

145                         case keyCode.PAGE_UP:

146                             this._move("previousPage", event);

147                             break;

148                         case keyCode.PAGE_DOWN:

149                             this._move("nextPage", event);

150                             break;

151                         case keyCode.UP:

152                             this._keyEvent("previous", event);

153                             break;

154                         case keyCode.DOWN:

155                             this._keyEvent("next", event);

156                             break;

157                     }

158                 },

159                 input: function (event) {

160                     if (suppressInput) {

161                         suppressInput = false;

162                         event.preventDefault();

163                         return;

164                     }

165                     this._searchTimeout(event);

166                 },

167                 focus: function () {

168                     this.selectedItem = null;

169                     this.previous = this._value();

170                 },

171                 blur: function (event) {

172                     if (this.cancelBlur) {

173                         delete this.cancelBlur;

174                         return;

175                     }

176 

177                     clearTimeout(this.searching);

178                     this.close(event);

179                     this._change(event);

180                 }

181             });

182 

183             this._initSource();

184             this.menu = $("<ul>")

185                 .addClass("ui-autocomplete")

186                 .appendTo(this.document.find(this.options.appendTo || "body")[0])

187                 .menu({

188                     // custom key handling for now

189                     input: $(),

190                     // disable ARIA support, the live region takes care of that

191                     role: null

192                 })

193                 .zIndex(this.element.zIndex() + 1)

194                 .hide()

195                 .data("menu");

196 

197             this._on(this.menu.element, {

198                 mousedown: function (event) {

199                     // prevent moving focus out of the text field

200                     event.preventDefault();

201 

202                     // IE doesn't prevent moving focus even with event.preventDefault()

203                     // so we set a flag to know when we should ignore the blur event

204                     this.cancelBlur = true;

205                     this._delay(function () {

206                         delete this.cancelBlur;

207                     });

208 

209                     // clicking on the scrollbar causes focus to shift to the body

210                     // but we can't detect a mouseup or a click immediately afterward

211                     // so we have to track the next mousedown and close the menu if

212                     // the user clicks somewhere outside of the autocomplete

213                     var menuElement = this.menu.element[0];

214                     if (!$(event.target).closest(".ui-menu-item").length) {

215                         this._delay(function () {

216                             var that = this;

217                             this.document.one("mousedown", function (event) {

218                                 if (event.target !== that.element[0] &&

219                                         event.target !== menuElement &&

220                                         !$.contains(menuElement, event.target)) {

221                                     that.close();

222                                 }

223                             });

224                         });

225                     }

226                 },

227                 menufocus: function (event, ui) {

228                     // #7024 - Prevent accidental activation of menu items in Firefox

229                     if (this.isNewMenu) {

230                         this.isNewMenu = false;

231                         if (event.originalEvent && /^mouse/.test(event.originalEvent.type)) {

232                             this.menu.blur();

233 

234                             this.document.one("mousemove", function () {

235                                 $(event.target).trigger(event.originalEvent);

236                             });

237 

238                             return;

239                         }

240                     }

241 

242                     // back compat for _renderItem using item.autocomplete, via #7810

243                     // TODO remove the fallback, see #8156

244                     var item = ui.item.data("ui-autocomplete-item") || ui.item.data("item.autocomplete");

245                     if (false !== this._trigger("focus", event, { item: item })) {

246                         // use value to match what will end up in the input, if it was a key event

247                         if (event.originalEvent && /^key/.test(event.originalEvent.type)) {

248                             this._value(item.value);

249                         }

250                     } else {

251                         // Normally the input is populated with the item's value as the

252                         // menu is navigated, causing screen readers to notice a change and

253                         // announce the item. Since the focus event was canceled, this doesn't

254                         // happen, so we update the live region so that screen readers can

255                         // still notice the change and announce it.

256                         this.liveRegion.text(item.value);

257                     }

258                 },

259                 menuselect: function (event, ui) {

260                     // back compat for _renderItem using item.autocomplete, via #7810

261                     // TODO remove the fallback, see #8156

262                     var item = ui.item.data("ui-autocomplete-item") || ui.item.data("item.autocomplete"),

263                         previous = this.previous;

264 

265                     // only trigger when focus was lost (click on menu)

266                     if (this.element[0] !== this.document[0].activeElement) {

267                         this.element.focus();

268                         this.previous = previous;

269                         // #6109 - IE triggers two focus events and the second

270                         // is asynchronous, so we need to reset the previous

271                         // term synchronously and asynchronously :-(

272                         this._delay(function () {

273                             this.previous = previous;

274                             this.selectedItem = item;

275                         });

276                     }

277 

278                     if (false !== this._trigger("select", event, { item: item })) {

279                         this._value(item.value);

280                     }

281                     // reset the term after the select event

282                     // this allows custom select handling to work properly

283                     this.term = this._value();

284 

285                     this.close(event);

286                     this.selectedItem = item;

287                 }

288             });

289 

290             this.liveRegion = $("<span>", {

291                 role: "status",

292                 "aria-live": "polite"

293             })

294                 .addClass("ui-helper-hidden-accessible");

295                 //.insertAfter(this.element);

296 

297             if ($.fn.bgiframe) {

298                 this.menu.element.bgiframe();

299             }

300 

301             // turning off autocomplete prevents the browser from remembering the

302             // value when navigating through history, so we re-enable autocomplete

303             // if the page is unloaded before the widget is destroyed. #7790

304             this._on(this.window, {

305                 beforeunload: function () {

306                     this.element.removeAttr("autocomplete");

307                 }

308             });

309         },//end _create

310 

311         _destroy: function () {

312             clearTimeout(this.searching);

313             this.element

314                 .removeClass("ui-autocomplete-input")

315                 .removeAttr("autocomplete");

316             this.menu.element.remove();

317             this.liveRegion.remove();

318         },

319 

320         _setOption: function (key, value) {

321             this._super(key, value);

322             if (key === "source") {

323                 this._initSource();

324             }

325             if (key === "appendTo") {

326                 this.menu.element.appendTo(this.document.find(value || "body")[0]);

327             }

328             if (key === "disabled" && value && this.xhr) {

329                 this.xhr.abort();

330             }

331         },

332 

333         _isMultiLine: function () {

334             // Textareas are always multi-line

335             if (this.element.is("textarea")) {

336                 return true;

337             }

338             // Inputs are always single-line, even if inside a contentEditable element

339             // IE also treats inputs as contentEditable

340             if (this.element.is("input")) {

341                 return false;

342             }

343             // All other element types are determined by whether or not they're contentEditable

344             return this.element.prop("isContentEditable");

345         },

346 

347         _initSource: function () {

348             var array, url,

349                 that = this;

350             if ($.isArray(this.options.source)) {

351                 array = this.options.source;

352                 this.source = function (request, response) {

353                     response($.ui.autocomplete.filter(array, request.term));

354                 };

355             } else if (typeof this.options.source === "string") {

356                 url = this.options.source;

357                 this.source = function (request, response) {

358                     if (that.xhr) {

359                         that.xhr.abort();

360                     }

361                     that.xhr = $.ajax({

362                         url: url,

363                         data: request,

364                         dataType: "json",

365                         success: function (data) {

366                             response(data);

367                         },

368                         error: function () {

369                             response([]);

370                         }

371                     });

372                 };

373             } else {

374                 this.source = this.options.source;

375             }

376         },

377 

378         _searchTimeout: function (event) {

379             clearTimeout(this.searching);

380             this.searching = this._delay(function () {

381                 // only search if the value has changed

382                 if (this.term !== this._value()) {

383                     this.selectedItem = null;

384                     this.search(null, event);

385                 }

386             }, this.options.delay);

387         },

388 

389         search: function (value, event) {

390             value = value != null ? value : this._value();

391 

392             // always save the actual value, not the one passed as an argument

393             this.term = this._value();

394 

395             if (value.length < this.options.minLength) {

396                 return this.close(event);

397             }

398 

399             if (this._trigger("search", event) === false) {

400                 return;

401             }

402 

403             return this._search(value);

404         },

405 

406         _search: function (value) {

407             this.pending++;

408             this.element.addClass("ui-autocomplete-loading");

409             this.cancelSearch = false;

410 

411             this.source({ term: value }, this._response());

412         },

413 

414         _response: function () {

415             var that = this,

416                 index = ++requestIndex;

417 

418             return function (content) {

419                 if (index === requestIndex) {

420                     that.__response(content);

421                 }

422 

423                 that.pending--;

424                 if (!that.pending) {

425                     that.element.removeClass("ui-autocomplete-loading");

426                 }

427             };

428         },

429 

430         __response: function (content) {

431             if (content) {

432                 content = this._normalize(content);

433             }

434             this._trigger("response", null, { content: content });

435             //content && content.length && 

436             if (!this.options.disabled && !this.cancelSearch) {

437                 this._suggest(content);

438                 this._trigger("open");

439             } else {

440                 // use ._close() instead of .close() so we don't cancel future searches

441                 this._close();

442             }

443         },

444 

445         close: function (event) {

446             this.cancelSearch = true;

447             this._close(event);

448         },

449 

450         _close: function (event) {

451             if (this.menu.element.is(":visible")) {

452                 this.menu.element.hide();

453                 this.menu.blur();

454                 this.isNewMenu = true;

455                 this._trigger("close", event);

456             }

457         },

458 

459         _change: function (event) {

460             if (this.previous !== this._value()) {

461                 this._trigger("change", event, { item: this.selectedItem });

462             }

463         },

464 

465         _normalize: function (items) {

466             // assume all items have the right format when the first item is complete

467             if (items.length && items[0].label && items[0].value) {

468                 return items;

469             }

470             return $.map(items, function (item) {

471                 if (typeof item === "string") {

472                     return {

473                         label: item,

474                         value: item

475                     };

476                 }

477                 return $.extend({

478                     label: item.label || item.value,

479                     value: item.value || item.label

480                 }, item);

481             });

482         },

483 

484         _suggest: function (items) {

485             var ul = this.menu.element

486                 .empty()

487                 .zIndex(this.element.zIndex() + 1);

488             this._renderMenu(ul, items);

489             this.menu.refresh();

490             // size and position menu

491             ul.show();

492             this._resizeMenu();

493             ul.position($.extend({

494                 of: this.element

495             }, this.options.position));

496 

497             if (this.options.autoFocus) {

498                 this.menu.next();

499             }

500         },

501 

502         _resizeMenu: function () {

503             var that = this;

504             var ul = this.menu.element;

505             

506             ul.outerWidth(                

507                 this.element.outerWidth()

508             );

509             

510             

511         },

512 

513         _limitNumberOfItems:function(available) {

514             return this.options.max && this.options.max < available

515             ? this.options.max

516             : available;

517         },

518 

519         _renderMenu: function (ul, items) {

520             var that = this;

521             var max = that._limitNumberOfItems(items.length);

522             var num = 0;

523             for (var i = 0; i < max; i++) {      

524                     that._renderItemData(ul, items[i]);

525                     num++;  

526             }

527             //$.each(items, function (index, item) {

528             //    that._renderItemData(ul, item);

529             //    num++;

530             //});           

531             var bottomlist = "<span class='autocomplete_bottom'>" +

532                                 "<span class='firstline'>Showing " +num+" Users</span>" +

533                                 "<span class='secondline' >"+

534                                     "<span class='sprite-icon sprite-icon-info-16x16'></span>"+

535                                     "<span class='autocomplete_bottom_txt'>Please type in more characters to narrow down the results.</span>" +

536                                 "</span></span>";

537             ul.append(bottomlist);

538             if (num == 0) {

539                 $('.secondline').hide();

540                 $('.firstline').text('No search results.');

541             }

542         },

543 

544         _renderItemData: function (ul, item) {

545             return this._renderItem(ul, item).data("ui-autocomplete-item", item);

546         },

547 

548         _renderItem: function (ul, item) {

549             return $("<li>")

550                 .append($("<a>").text(item.label))

551                 .appendTo(ul);

552         },

553 

554         _move: function (direction, event) {

555             if (!this.menu.element.is(":visible")) {

556                 this.search(null, event);

557                 return;

558             }

559             if (this.menu.isFirstItem() && /^previous/.test(direction) ||

560                     this.menu.isLastItem() && /^next/.test(direction)) {

561                 this._value(this.term);

562                 this.menu.blur();

563                 return;

564             }

565             this.menu[direction](event);

566         },

567 

568         widget: function () {

569             return this.menu.element;

570         },

571 

572         _value: function () {

573             return this.valueMethod.apply(this.element, arguments);

574         },

575 

576         _keyEvent: function (keyEvent, event) {

577             if (!this.isMultiLine || this.menu.element.is(":visible")) {

578                 this._move(keyEvent, event);

579 

580                 // prevents moving cursor to beginning/end of the text field in some browsers

581                 event.preventDefault();

582             }

583         }

584     });//end $.widget()

585 

586 

587     $.extend($.ui.autocomplete, {

588         escapeRegex: function (value) {

589             return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");

590         },

591         filter: function (array, term) {

592             var matcher = new RegExp($.ui.autocomplete.escapeRegex(term), "i");

593             return $.grep(array, function (value) {

594                 return matcher.test(value.label || value.value || value);

595             });

596         }

597     });

598 

599     // live region extension, adding a `messages` option

600     // NOTE: This is an experimental API. We are still investigating

601     // a full solution for string manipulation and internationalization.

602     $.widget("ui.autocomplete", $.ui.autocomplete, {

603         options: {

604             messages: {

605                 noResults: "No search results.",

606                 results: function (amount) {

607                     return amount + (amount > 1 ? " results are" : " result is") +

608                         " available, use up and down arrow keys to navigate.";

609                 }

610             }

611         },

612 

613         __response: function (content) {

614             var message;

615             this._superApply(arguments);

616             if (this.options.disabled || this.cancelSearch) {

617                 return;

618             }

619             if (content && content.length) {

620                 message = this.options.messages.results(content.length);

621             } else {

622                 message = this.options.messages.noResults;

623             }

624             this.liveRegion.text(message).css('position','');

625         }

626     });

627 

628 

629 }(jQuery));
View Code

 

你可能感兴趣的:(autocomplete)