PageSourceSearch

https://sportwetter-forum.de/wp-content/plugins/asgaros-forum/libs/jquery.atwho.js?ver=3.4.0

js sportwetter-forum.de collected 2026-09-24 11:17:20 UTC 35,075 bytes, 1,212 lines download raw bytes

1/**
2 * at.js - 1.5.4
3 * Copyright (c) 2017 chord.luo <[email protected]>;
4 * Homepage: http://ichord.github.com/At.js
5 * License: MIT
6 */
7(function (root, factory) {
8  if (typeof define === 'function' && define.amd) {
9    // AMD. Register as an anonymous module unless amdModuleId is set
10    define(["jquery"], function (a0) {
11      return (factory(a0));
12    });
13  } else if (typeof exports === 'object') {
14    // Node. Does not work with strict CommonJS, but
15    // only CommonJS-like environments that support module.exports,
16    // like Node.
17    module.exports = factory(require("jquery"));
18  } else {
19    factory(jQuery);
20  }
21}(this, function ($) {
22var DEFAULT_CALLBACKS, KEY_CODE;
23
24KEY_CODE = {
25  ESC: 27,
26  TAB: 9,
27  ENTER: 13,
28  CTRL: 17,
29  A: 65,
30  P: 80,
31  N: 78,
32  LEFT: 37,
33  UP: 38,
34  RIGHT: 39,
35  DOWN: 40,
36  BACKSPACE: 8,
37  SPACE: 32
38};
39
40DEFAULT_CALLBACKS = {
41  beforeSave: function(data) {
42    return Controller.arrayToDefaultHash(data);
43  },
44  matcher: function(flag, subtext, should_startWithSpace, acceptSpaceBar) {
45    var _a, _y, match, regexp, space;
46    flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
47    if (should_startWithSpace) {
48      flag = '(?:^|\\s)' + flag;
49    }
50    _a = decodeURI("%C3%80");
51    _y = decodeURI("%C3%BF");
52    space = acceptSpaceBar ? "\ " : "";
53    regexp = new RegExp(flag + "([A-Za-z" + _a + "-" + _y + "0-9_" + space + "\'\.\+\-]*)$|" + flag + "([^\\x00-\\xff]*)$", 'gi');
54    match = regexp.exec(subtext);
55    if (match) {
56      return match[2] || match[1];
57    } else {
58      return null;
59    }
60  },
61  filter: function(query, data, searchKey) {
62    var _results, i, item, len;
63    _results = [];
64    for (i = 0, len = data.length; i < len; i++) {
65      item = data[i];
66      if (~new String(item[searchKey]).toLowerCase().indexOf(query.toLowerCase())) {
67        _results.push(item);
68      }
69    }
70    return _results;
71  },
72  remoteFilter: null,
73  sorter: function(query, items, searchKey) {
74    var _results, i, item, len;
75    if (!query) {
76      return items;
77    }
78    _results = [];
79    for (i = 0, len = items.length; i < len; i++) {
80      item = items[i];
81      item.atwho_order = new String(item[searchKey]).toLowerCase().indexOf(query.toLowerCase());
82      if (item.atwho_order > -1) {
83        _results.push(item);
84      }
85    }
86    return _results.sort(function(a, b) {
87      return a.atwho_order - b.atwho_order;
88    });
89  },
90  tplEval: function(tpl, map) {
91    var error, error1, template;
92    template = tpl;
93    try {
94      if (typeof tpl !== 'string') {
95        template = tpl(map);
96      }
97      return template.replace(/\$\{([^\}]*)\}/g, function(tag, key, pos) {
98        return map[key];
99      });
100    } catch (error1) {
101      error = error1;
102      return "";
103    }
104  },
105  highlighter: function(li, query) {
106    var regexp;
107    if (!query) {
108      return li;
109    }
110    regexp = new RegExp(">\\s*([^\<]*?)(" + query.replace("+", "\\+") + ")([^\<]*)\\s*<", 'ig');
111    return li.replace(regexp, function(str, $1, $2, $3) {
112      return '> ' + $1 + '<strong>' + $2 + '</strong>' + $3 + ' <';
113    });
114  },
115  beforeInsert: function(value, $li, e) {
116    return value;
117  },
118  beforeReposition: function(offset) {
119    return offset;
120  },
121  afterMatchFailed: function(at, el) {}
122};
123
124var App;
125
126App = (function() {
127  function App(inputor) {
128    this.currentFlag = null;
129    this.controllers = {};
130    this.aliasMaps = {};
131    this.$inputor = $(inputor);
132    this.setupRootElement();
133    this.listen();
134  }
135
136  App.prototype.createContainer = function(doc) {
137    var ref;
138    if ((ref = this.$el) != null) {
139      ref.remove();
140    }
141    return $(doc.body).append(this.$el = $("<div class='atwho-container'></div>"));
142  };
143
144  App.prototype.setupRootElement = function(iframe, asRoot) {
145    var error, error1;
146    if (asRoot == null) {
147      asRoot = false;
148    }
149    if (iframe) {
150      this.window = iframe.contentWindow;
151      this.document = iframe.contentDocument || this.window.document;
152      this.iframe = iframe;
153    } else {
154      this.document = this.$inputor[0].ownerDocument;
155      this.window = this.document.defaultView || this.document.parentWindow;
156      try {
157        this.iframe = this.window.frameElement;
158      } catch (error1) {
159        error = error1;
160        this.iframe = null;
161        if ($.fn.atwho.debug) {
162          throw new Error("iframe auto-discovery is failed.\nPlease use `setIframe` to set the target iframe manually.\n" + error);
163        }
164      }
165    }
166    return this.createContainer((this.iframeAsRoot = asRoot) ? this.document : document);
167  };
168
169  App.prototype.controller = function(at) {
170    var c, current, currentFlag, ref;
171    if (this.aliasMaps[at]) {
172      current = this.controllers[this.aliasMaps[at]];
173    } else {
174      ref = this.controllers;
175      for (currentFlag in ref) {
176        c = ref[currentFlag];
177        if (currentFlag === at) {
178          current = c;
179          break;
180        }
181      }
182    }
183    if (current) {
184      return current;
185    } else {
186      return this.controllers[this.currentFlag];
187    }
188  };
189
190  App.prototype.setContextFor = function(at) {
191    this.currentFlag = at;
192    return this;
193  };
194
195  App.prototype.reg = function(flag, setting) {
196    var base, controller;
197    controller = (base = this.controllers)[flag] || (base[flag] = this.$inputor.is('[contentEditable]') ? new EditableController(this, flag) : new TextareaController(this, flag));
198    if (setting.alias) {
199      this.aliasMaps[setting.alias] = flag;
200    }
201    controller.init(setting);
202    return this;
203  };
204
205  App.prototype.listen = function() {
206    return this.$inputor.on('compositionstart', (function(_this) {
207      return function(e) {
208        var ref;
209        if ((ref = _this.controller()) != null) {
210          ref.view.hide();
211        }
212        _this.isComposing = true;
213        return null;
214      };
215    })(this)).on('compositionend', (function(_this) {
216      return function(e) {
217        _this.isComposing = false;
218        setTimeout(function(e) {
219          return _this.dispatch(e);
220        });
221        return null;
222      };
223    })(this)).on('keyup.atwhoInner', (function(_this) {
224      return function(e) {
225        return _this.onKeyup(e);
226      };
227    })(this)).on('keydown.atwhoInner', (function(_this) {
228      return function(e) {
229        return _this.onKeydown(e);
230      };
231    })(this)).on('blur.atwhoInner', (function(_this) {
232      return function(e) {
233        var c;
234        if (c = _this.controller()) {
235          c.expectedQueryCBId = null;
236          return c.view.hide(e, c.getOpt("displayTimeout"));
237        }
238      };
239    })(this)).on('click.atwhoInner', (function(_this) {
240      return function(e) {
241        return _this.dispatch(e);
242      };
243    })(this)).on('scroll.atwhoInner', (function(_this) {
244      return function() {
245        var lastScrollTop;
246        lastScrollTop = _this.$inputor.scrollTop();
247        return function(e) {
248          var currentScrollTop, ref;
249          currentScrollTop = e.target.scrollTop;
250          if (lastScrollTop !== currentScrollTop) {
251            if ((ref = _this.controller()) != null) {
252              ref.view.hide(e);
253            }
254          }
255          lastScrollTop = currentScrollTop;
256          return true;
257        };
258      };
259    })(this)());
260  };
261
262  App.prototype.shutdown = function() {
263    var _, c, ref;
264    ref = this.controllers;
265    for (_ in ref) {
266      c = ref[_];
267      c.destroy();
268      delete this.controllers[_];
269    }
270    this.$inputor.off('.atwhoInner');
271    return this.$el.remove();
272  };
273
274  App.prototype.dispatch = function(e) {
275    var _, c, ref, results;
276    ref = this.controllers;
277    results = [];
278    for (_ in ref) {
279      c = ref[_];
280      results.push(c.lookUp(e));
281    }
282    return results;
283  };
284
285  App.prototype.onKeyup = function(e) {
286    var ref;
287    switch (e.keyCode) {
288      case KEY_CODE.ESC:
289        e.preventDefault();
290        if ((ref = this.controller()) != null) {
291          ref.view.hide();
292        }
293        break;
294      case KEY_CODE.DOWN:
295      case KEY_CODE.UP:
296      case KEY_CODE.CTRL:
297      case KEY_CODE.ENTER:
298        $.noop();
299        break;
300      case KEY_CODE.P:
301      case KEY_CODE.N:
302        if (!e.ctrlKey) {
303          this.dispatch(e);
304        }
305        break;
306      default:
307        this.dispatch(e);
308    }
309  };
310
311  App.prototype.onKeydown = function(e) {
312    var ref, view;
313    view = (ref = this.controller()) != null ? ref.view : void 0;
314    if (!(view && view.visible())) {
315      return;
316    }
317    switch (e.keyCode) {
318      case KEY_CODE.ESC:
319        e.preventDefault();
320        view.hide(e);
321        break;
322      case KEY_CODE.UP:
323        e.preventDefault();
324        view.prev();
325        break;
326      case KEY_CODE.DOWN:
327        e.preventDefault();
328        view.next();
329        break;
330      case KEY_CODE.P:
331        if (!e.ctrlKey) {
332          return;
333        }
334        e.preventDefault();
335        view.prev();
336        break;
337      case KEY_CODE.N:
338        if (!e.ctrlKey) {
339          return;
340        }
341        e.preventDefault();
342        view.next();
343        break;
344      case KEY_CODE.TAB:
345      case KEY_CODE.ENTER:
346      case KEY_CODE.SPACE:
347        if (!view.visible()) {
348          return;
349        }
350        if (!this.controller().getOpt('spaceSelectsMatch') && e.keyCode === KEY_CODE.SPACE) {
351          return;
352        }
353        if (!this.controller().getOpt('tabSelectsMatch') && e.keyCode === KEY_CODE.TAB) {
354          return;
355        }
356        if (view.highlighted()) {
357          e.preventDefault();
358          view.choose(e);
359        } else {
360          view.hide(e);
361        }
362        break;
363      default:
364        $.noop();
365    }
366  };
367
368  return App;
369
370})();
371
372var Controller,
373  slice = [].slice;
374
375Controller = (function() {
376  Controller.prototype.uid = function() {
377    return (Math.random().toString(16) + "000000000").substr(2, 8) + (new Date().getTime());
378  };
379
380  function Controller(app, at1) {
381    this.app = app;
382    this.at = at1;
383    this.$inputor = this.app.$inputor;
384    this.id = this.$inputor[0].id || this.uid();
385    this.expectedQueryCBId = null;
386    this.setting = null;
387    this.query = null;
388    this.pos = 0;
389    this.range = null;
390    if ((this.$el = $("#atwho-ground-" + this.id, this.app.$el)).length === 0) {
391      this.app.$el.append(this.$el = $("<div id='atwho-ground-" + this.id + "'></div>"));
392    }
393    this.model = new Model(this);
394    this.view = new View(this);
395  }
396
397  Controller.prototype.init = function(setting) {
398    this.setting = $.extend({}, this.setting || $.fn.atwho["default"], setting);
399    this.view.init();
400    return this.model.reload(this.setting.data);
401  };
402
403  Controller.prototype.destroy = function() {
404    this.trigger('beforeDestroy');
405    this.model.destroy();
406    this.view.destroy();
407    return this.$el.remove();
408  };
409
410  Controller.prototype.callDefault = function() {
411    var args, error, error1, funcName;
412    funcName = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
413    try {
414      return DEFAULT_CALLBACKS[funcName].apply(this, args);
415    } catch (error1) {
416      error = error1;
417      return $.error(error + " Or maybe At.js doesn't have function " + funcName);
418    }
419  };
420
421  Controller.prototype.trigger = function(name, data) {
422    var alias, eventName;
423    if (data == null) {
424      data = [];
425    }
426    data.push(this);
427    alias = this.getOpt('alias');
428    eventName = alias ? name + "-" + alias + ".atwho" : name + ".atwho";
429    return this.$inputor.trigger(eventName, data);
430  };
431
432  Controller.prototype.callbacks = function(funcName) {
433    return this.getOpt("callbacks")[funcName] || DEFAULT_CALLBACKS[funcName];
434  };
435
436  Controller.prototype.getOpt = function(at, default_value) {
437    var e, error1;
438    try {
439      return this.setting[at];
440    } catch (error1) {
441      e = error1;
442      return null;
443    }
444  };
445
446  Controller.prototype.insertContentFor = function($li) {
447    var data, tpl;
448    tpl = this.getOpt('insertTpl');
449    data = $.extend({}, $li.data('item-data'), {
450      'atwho-at': this.at
451    });
452    return this.callbacks("tplEval").call(this, tpl, data, "onInsert");
453  };
454
455  Controller.prototype.renderView = function(data) {
456    var searchKey;
457    searchKey = this.getOpt("searchKey");
458    data = this.callbacks("sorter").call(this, this.query.text, data.slice(0, 1001), searchKey);
459    return this.view.render(data.slice(0, this.getOpt('limit')));
460  };
461
462  Controller.arrayToDefaultHash = function(data) {
463    var i, item, len, results;
464    if (!$.isArray(data)) {
465      return data;
466    }
467    results = [];
468    for (i = 0, len = data.length; i < len; i++) {
469      item = data[i];
470      if ($.isPlainObject(item)) {
471        results.push(item);
472      } else {
473        results.push({
474          name: item
475        });
476      }
477    }
478    return results;
479  };
480
481  Controller.prototype.lookUp = function(e) {
482    var query, wait;
483    if (e && e.type === 'click' && !this.getOpt('lookUpOnClick')) {
484      return;
485    }
486    if (this.getOpt('suspendOnComposing') && this.app.isComposing) {
487      return;
488    }
489    query = this.catchQuery(e);
490    if (!query) {
491      this.expectedQueryCBId = null;
492      return query;
493    }
494    this.app.setContextFor(this.at);
495    if (wait = this.getOpt('delay')) {
496      this._delayLookUp(query, wait);
497    } else {
498      this._lookUp(query);
499    }
500    return query;
501  };
502
503  Controller.prototype._delayLookUp = function(query, wait) {
504    var now, remaining;
505    now = Date.now ? Date.now() : new Date().getTime();
506    this.previousCallTime || (this.previousCallTime = now);
507    remaining = wait - (now - this.previousCallTime);
508    if ((0 < remaining && remaining < wait)) {
509      this.previousCallTime = now;
510      this._stopDelayedCall();
511      return this.delayedCallTimeout = setTimeout((function(_this) {
512        return function() {
513          _this.previousCallTime = 0;
514          _this.delayedCallTimeout = null;
515          return _this._lookUp(query);
516        };
517      })(this), wait);
518    } else {
519      this._stopDelayedCall();
520      if (this.previousCallTime !== now) {
521        this.previousCallTime = 0;
522      }
523      return this._lookUp(query);
524    }
525  };
526
527  Controller.prototype._stopDelayedCall = function() {
528    if (this.delayedCallTimeout) {
529      clearTimeout(this.delayedCallTimeout);
530      return this.delayedCallTimeout = null;
531    }
532  };
533
534  Controller.prototype._generateQueryCBId = function() {
535    return {};
536  };
537
538  Controller.prototype._lookUp = function(query) {
539    var _callback;
540    _callback = function(queryCBId, data) {
541      if (queryCBId !== this.expectedQueryCBId) {
542        return;
543      }
544      if (data && data.length > 0) {
545        return this.renderView(this.constructor.arrayToDefaultHash(data));
546      } else {
547        return this.view.hide();
548      }
549    };
550    this.expectedQueryCBId = this._generateQueryCBId();
551    return this.model.query(query.text, $.proxy(_callback, this, this.expectedQueryCBId));
552  };
553
554  return Controller;
555
556})();
557
558var TextareaController,
559  extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
560  hasProp = {}.hasOwnProperty;
561
562TextareaController = (function(superClass) {
563  extend(TextareaController, superClass);
564
565  function TextareaController() {
566    return TextareaController.__super__.constructor.apply(this, arguments);
567  }
568
569  TextareaController.prototype.catchQuery = function() {
570    var caretPos, content, end, isString, query, start, subtext;
571    content = this.$inputor.val();
572    caretPos = this.$inputor.caret('pos', {
573      iframe: this.app.iframe
574    });
575    subtext = content.slice(0, caretPos);
576    query = this.callbacks("matcher").call(this, this.at, subtext, this.getOpt('startWithSpace'), this.getOpt("acceptSpaceBar"));
577    isString = typeof query === 'string';
578    if (isString && query.length < this.getOpt('minLen', 0)) {
579      return;
580    }
581    if (isString && query.length <= this.getOpt('maxLen', 20)) {
582      start = caretPos - query.length;
583      end = start + query.length;
584      this.pos = start;
585      query = {
586        'text': query,
587        'headPos': start,
588        'endPos': end
589      };
590      this.trigger("matched", [this.at, query.text]);
591    } else {
592      query = null;
593      this.view.hide();
594    }
595    return this.query = query;
596  };
597
598  TextareaController.prototype.rect = function() {
599    var c, iframeOffset, scaleBottom;
600    if (!(c = this.$inputor.caret('offset', this.pos - 1, {
601      iframe: this.app.iframe
602    }))) {
603      return;
604    }
605    if (this.app.iframe && !this.app.iframeAsRoot) {
606      iframeOffset = $(this.app.iframe).offset();
607      c.left += iframeOffset.left;
608      c.top += iframeOffset.top;
609    }
610    scaleBottom = this.app.document.selection ? 0 : 2;
611    return {
612      left: c.left,
613      top: c.top,
614      bottom: c.top + c.height + scaleBottom
615    };
616  };
617
618  TextareaController.prototype.insert = function(content, $li) {
619    var $inputor, source, startStr, suffix, text;
620    $inputor = this.$inputor;
621    source = $inputor.val();
622    startStr = source.slice(0, Math.max(this.query.headPos - this.at.length, 0));
623    suffix = (suffix = this.getOpt('suffix')) === "" ? suffix : suffix || " ";
624    content += suffix;
625    text = "" + startStr + content + (source.slice(this.query['endPos'] || 0));
626    $inputor.val(text);
627    $inputor.caret('pos', startStr.length + content.length, {
628      iframe: this.app.iframe
629    });
630    if (!$inputor.is(':focus')) {
631      $inputor.focus();
632    }
633    return $inputor.change();
634  };
635
636  return TextareaController;
637
638})(Controller);
639
640var EditableController,
641  extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
642  hasProp = {}.hasOwnProperty;
643
644EditableController = (function(superClass) {
645  extend(EditableController, superClass);
646
647  function EditableController() {
648    return EditableController.__super__.constructor.apply(this, arguments);
649  }
650
651  EditableController.prototype._getRange = function() {
652    var sel;
653    sel = this.app.window.getSelection();
654    if (sel.rangeCount > 0) {
655      return sel.getRangeAt(0);
656    }
657  };
658
659  EditableController.prototype._setRange = function(position, node, range) {
660    if (range == null) {
661      range = this._getRange();
662    }
663    if (!(range && node)) {
664      return;
665    }
666    node = $(node)[0];
667    if (position === 'after') {
668      range.setEndAfter(node);
669      range.setStartAfter(node);
670    } else {
671      range.setEndBefore(node);
672      range.setStartBefore(node);
673    }
674    range.collapse(false);
675    return this._clearRange(range);
676  };
677
678  EditableController.prototype._clearRange = function(range) {
679    var sel;
680    if (range == null) {
681      range = this._getRange();
682    }
683    sel = this.app.window.getSelection();
684    if (this.ctrl_a_pressed == null) {
685      sel.removeAllRanges();
686      return sel.addRange(range);
687    }
688  };
689
690  EditableController.prototype._movingEvent = function(e) {
691    var ref;
692    return e.type === 'click' || ((ref = e.which) === KEY_CODE.RIGHT || ref === KEY_CODE.LEFT || ref === KEY_CODE.UP || ref === KEY_CODE.DOWN);
693  };
694
695  EditableController.prototype._unwrap = function(node) {
696    var next;
697    node = $(node).unwrap().get(0);
698    if ((next = node.nextSibling) && next.nodeValue) {
699      node.nodeValue += next.nodeValue;
700      $(next).remove();
701    }
702    return node;
703  };
704
705  EditableController.prototype.catchQuery = function(e) {
706    var $inserted, $query, _range, index, inserted, isString, lastNode, matched, offset, query, query_content, range;
707    if (!(range = this._getRange())) {
708      return;
709    }
710    if (!range.collapsed) {
711      return;
712    }
713    if (e.which === KEY_CODE.ENTER) {
714      ($query = $(range.startContainer).closest('.atwho-query')).contents().unwrap();
715      if ($query.is(':empty')) {
716        $query.remove();
717      }
718      ($query = $(".atwho-query", this.app.document)).text($query.text()).contents().last(
718).unwrap();
719      this._clearRange();
720      return;
721    }
722    if (/firefox/i.test(navigator.userAgent)) {
723      if ($(range.startContainer).is(this.$inputor)) {
724        this._clearRange();
725        return;
726      }
727      if (e.which === KEY_CODE.BACKSPACE && range.startContainer.nodeType === document.ELEMENT_NODE && (offset = range.startOffset - 1) >= 0) {
728        _range = range.cloneRange();
729        _range.setStart(range.startContainer, offset);
730        if ($(_range.cloneContents()).contents().last().is('.atwho-inserted')) {
731          inserted = $(range.startContainer).contents().get(offset);
732          this._setRange('after', $(inserted).contents().last());
733        }
734      } else if (e.which === KEY_CODE.LEFT && range.startContainer.nodeType === document.TEXT_NODE) {
735        $inserted = $(range.startContainer.previousSibling);
736        if ($inserted.is('.atwho-inserted') && range.startOffset === 0) {
737          this._setRange('after', $inserted.contents().last());
738        }
739      }
740    }
741    $(range.startContainer).closest('.atwho-inserted').addClass('atwho-query').siblings().removeClass('atwho-query');
742    if (($query = $(".atwho-query", this.app.document)).length > 0 && $query.is(':empty') && $query.text().length === 0) {
743      $query.remove();
744    }
745    if (!this._movingEvent(e)) {
746      $query.removeClass('atwho-inserted');
747    }
748    if ($query.length > 0) {
749      switch (e.which) {
750        case KEY_CODE.LEFT:
751          this._setRange('before', $query.get(0), range);
752          $query.removeClass('atwho-query');
753          return;
754        case KEY_CODE.RIGHT:
755          this._setRange('after', $query.get(0).nextSibling, range);
756          $query.removeClass('atwho-query');
757          return;
758      }
759    }
760    if ($query.length > 0 && (query_content = $query.attr('data-atwho-at-query'))) {
761      $query.empty().html(query_content).attr('data-atwho-at-query', null);
762      this._setRange('after', $query.get(0), range);
763    }
764    _range = range.cloneRange();
765    _range.setStart(range.startContainer, 0);
766    matched = this.callbacks("matcher").call(this, this.at, _range.toString(), this.getOpt('startWithSpace'), this.getOpt("acceptSpaceBar"));
767    isString = typeof matched === 'string';
768    if ($query.length === 0 && isString && (index = range.startOffset - this.at.length - matched.length) >= 0) {
769      range.setStart(range.startContainer, index);
770      $query = $('<span/>', this.app.document).attr(this.getOpt("editableAtwhoQueryAttrs")).addClass('atwho-query');
771      range.surroundContents($query.get(0));
772      lastNode = $query.contents().last().get(0);
773      if (lastNode) {
774        if (/firefox/i.test(navigator.userAgent)) {
775          range.setStart(lastNode, lastNode.length);
776          range.setEnd(lastNode, lastNode.length);
777          this._clearRange(range);
778        } else {
779          this._setRange('after', lastNode, range);
780        }
781      }
782    }
783    if (isString && matched.length < this.getOpt('minLen', 0)) {
784      return;
785    }
786    if (isString && matched.length <= this.getOpt('maxLen', 20)) {
787      query = {
788        text: matched,
789        el: $query
790      };
791      this.trigger("matched", [this.at, query.text]);
792      return this.query = query;
793    } else {
794      this.view.hide();
795      this.query = {
796        el: $query
797      };
798      if ($query.text().indexOf(this.at) >= 0) {
799        if (this._movingEvent(e) && $query.hasClass('atwho-inserted')) {
800          $query.removeClass('atwho-query');
801        } else if (false !== this.callbacks('afterMatchFailed').call(this, this.at, $query)) {
802          this._setRange("after", this._unwrap($query.text($query.text()).contents().first()));
803        }
804      }
805      return null;
806    }
807  };
808
809  EditableController.prototype.rect = function() {
810    var $iframe, iframeOffset, rect;
811    rect = this.query.el.offset();
812    if (!(rect && this.query.el[0].getClientRects().length)) {
813      return;
814    }
815    if (this.app.iframe && !this.app.iframeAsRoot) {
816      iframeOffset = ($iframe = $(this.app.iframe)).offset();
817      rect.left += iframeOffset.left - this.$inputor.scrollLeft();
818      rect.top += iframeOffset.top - this.$inputor.scrollTop();
819    }
820    rect.bottom = rect.top + this.query.el.height();
821    return rect;
822  };
823
824  EditableController.prototype.insert = function(content, $li) {
825    var data, overrides, range, suffix, suffixNode;
826    if (!this.$inputor.is(':focus')) {
827      this.$inputor.focus();
828    }
829    overrides = this.getOpt('functionOverrides');
830    if (overrides.insert) {
831      return overrides.insert.call(this, content, $li);
832    }
833    suffix = (suffix = this.getOpt('suffix')) === "" ? suffix : suffix || "\u00A0";
834    data = $li.data('item-data');
835    this.query.el.removeClass('atwho-query').addClass('atwho-inserted').html(content).attr('data-atwho-at-query', "" + data['atwho-at'] + this.query.text).attr('contenteditable', "false");
836    if (range = this._getRange()) {
837      if (this.query.el.length) {
838        range.setEndAfter(this.query.el[0]);
839      }
840      range.collapse(false);
841      range.insertNode(suffixNode = this.app.document.createTextNode("" + suffix));
842      this._setRange('after', suffixNode, range);
843    }
844    if (!this.$inputor.is(':focus')) {
845      this.$inputor.focus();
846    }
847    return this.$inputor.change();
848  };
849
850  return EditableController;
851
852})(Controller);
853
854var Model;
855
856Model = (function() {
857  function Model(context) {
858    this.context = context;
859    this.at = this.context.at;
860    this.storage = this.context.$inputor;
861  }
862
863  Model.prototype.destroy = function() {
864    return this.storage.data(this.at, null);
865  };
866
867  Model.prototype.saved = function() {
868    return this.fetch() > 0;
869  };
870
871  Model.prototype.query = function(query, callback) {
872    var _remoteFilter, data, searchKey;
873    data = this.fetch();
874    searchKey = this.context.getOpt("searchKey");
875    data = this.context.callbacks('filter').call(this.context, query, data, searchKey) || [];
876    _remoteFilter = this.context.callbacks('remoteFilter');
877    if (data.length > 0 || (!_remoteFilter && data.length === 0)) {
878      return callback(data);
879    } else {
880      return _remoteFilter.call(this.context, query, callback);
881    }
882  };
883
884  Model.prototype.fetch = function() {
885    return this.storage.data(this.at) || [];
886  };
887
888  Model.prototype.save = function(data) {
889    return this.storage.data(this.at, this.context.callbacks("beforeSave").call(this.context, data || []));
890  };
891
892  Model.prototype.load = function(data) {
893    if (!(this.saved() || !data)) {
894      return this._load(data);
895    }
896  };
897
898  Model.prototype.reload = function(data) {
899    return this._load(data);
900  };
901
902  Model.prototype._load = function(data) {
903    if (typeof data === "string") {
904      return $.ajax(data, {
905        dataType: "json"
906      }).done((function(_this) {
907        return function(data) {
908          return _this.save(data);
909        };
910      })(this));
911    } else {
912      return this.save(data);
913    }
914  };
915
916  return Model;
917
918})();
919
920var View;
921
922View = (function() {
923  function View(context) {
924    this.context = context;
925    this.$el = $("<div class='atwho-view'><ul class='atwho-view-ul'></ul></div>");
926    this.$elUl = this.$el.children();
927    this.timeoutID = null;
928    this.context.$el.append(this.$el);
929    this.bindEvent();
930  }
931
932  View.prototype.init = function() {
933    var header_tpl, id;
934    id = this.context.getOpt("alias") || this.context.at.charCodeAt(0);
935    header_tpl = this.context.getOpt("headerTpl");
936    if (header_tpl && this.$el.children().length === 1) {
937      this.$el.prepend(header_tpl);
938    }
939    return this.$el.attr({
940      'id': "at-view-" + id
941    });
942  };
943
944  View.prototype.destroy = function() {
945    return this.$el.remove();
946  };
947
948  View.prototype.bindEvent = function() {
949    var $menu, lastCoordX, lastCoordY;
950    $menu = this.$el.find('ul');
951    lastCoordX = 0;
952    lastCoordY = 0;
953    return $menu.on('mousemove.atwho-view', 'li', (function(_this) {
954      return function(e) {
955        var $cur;
956        if (lastCoordX === e.clientX && lastCoordY === e.clientY) {
957          return;
958        }
959        lastCoordX = e.clientX;
960        lastCoordY = e.clientY;
961        $cur = $(e.currentTarget);
962        if ($cur.hasClass('cur')) {
963          return;
964        }
965        $menu.find('.cur').removeClass('cur');
966        return $cur.addClass('cur');
967      };
968    })(this)).on('click.atwho-view', 'li', (function(_this) {
969      return function(e) {
970        $menu.find('.cur').removeClass('cur');
971        $(e.currentTarget).addClass('cur');
972        _this.choose(e);
973        return e.preventDefault();
974      };
975    })(this));
976  };
977
978  View.prototype.visible = function() {
979    return $.expr.filters.visible(this.$el[0]);
980  };
981
982  View.prototype.highlighted = function() {
983    return this.$el.find(".cur").length > 0;
984  };
985
986  View.prototype.choose = function(e) {
987    var $li, content;
988    if (($li = this.$el.find(".cur")).length) {
989      content = this.context.insertContentFor($li);
990      this.context._stopDelayedCall();
991      this.context.insert(this.context.callbacks("beforeInsert").call(this.context, content, $li, e), $li);
992      this.context.trigger("inserted", [$li, e]);
993      this.hide(e);
994    }
995    if (this.context.getOpt("hideWithoutSuffix")) {
996      return this.stopShowing = true;
997    }
998  };
999
1000  View.prototype.reposition = function(rect) {
1001    var _window, offset, overflowOffset, ref;
1002    _window = this.context.app.iframeAsRoot ? this.context.app.window : window;
1003    if (rect.bottom + this.$el.height() - $(_window).scrollTop() > $(_window).height()) {
1004      rect.bottom = rect.top - this.$el.height();
1005    }
1006    if (rect.left > (overflowOffset = $(_window).width() - this.$el.width() - 5)) {
1007      rect.left = overflowOffset;
1008    }
1009    offset = {
1010      left: rect.left,
1011      top: rect.bottom
1012    };
1013    if ((ref = this.context.callbacks("beforeReposition")) != null) {
1014      ref.call(this.context, offset);
1015    }
1016    this.$el.offset(offset);
1017    return this.context.trigger("reposition", [offset]);
1018  };
1019
1020  View.prototype.next = function() {
1021    var cur, next, nextEl, offset;
1022    cur = this.$el.find('.cur').removeClass('cur');
1023    next = cur.next();
1024    if (!next.length) {
1025      next = this.$el.find('li:first');
1026    }
1027    next.addClass('cur');
1028    nextEl = next[0];
1029    offset = nextEl.offsetTop + nextEl.offsetHeight + (nextEl.nextSibling ? nextEl.nextSibling.offsetHeight : 0);
1030    return this.scrollTop(Math.max(0, offset - this.$el.height()));
1031  };
1032
1033  View.prototype.prev = function() {
1034    var cur, offset, prev, prevEl;
1035    cur = this.$el.find('.cur').removeClass('cur');
1036    prev = cur.prev();
1037    if (!prev.length) {
1038      prev = this.$el.find('li:last');
1039    }
1040    prev.addClass('cur');
1041    prevEl = prev[0];
1042    offset = prevEl.offsetTop + prevEl.offsetHeight + (prevEl.nextSibling ? prevEl.nextSibling.offsetHeight : 0);
1043    return this.scrollTop(Math.max(0, offset - this.$el.height()));
1044  };
1045
1046  View.prototype.scrollTop = function(scrollTop) {
1047    var scrollDuration;
1048    scrollDuration = this.context.getOpt('scrollDuration');
1049    if (scrollDuration) {
1050      return this.$elUl.animate({
1051        scrollTop: scrollTop
1052      }, scrollDuration);
1053    } else {
1054      return this.$elUl.scrollTop(scrollTop);
1055    }
1056  };
1057
1058  View.prototype.show = function() {
1059    var rect;
1060    if (this.stopShowing) {
1061      this.stopShowing = false;
1062      return;
1063    }
1064    if (!this.visible()) {
1065      this.$el.show();
1066      this.$el.scrollTop(0);
1067      this.context.trigger('shown');
1068    }
1069    if (rect = this.context.rect()) {
1070      return this.reposition(rect);
1071    }
1072  };
1073
1074  View.prototype.hide = function(e, time) {
1075    var callback;
1076    if (!this.visible()) {
1077      return;
1078    }
1079    if (isNaN(time)) {
1080      this.$el.hide();
1081      return this.context.trigger('hidden', [e]);
1082    } else {
1083      callback = (function(_this) {
1084        return function() {
1085          return _this.hide();
1086        };
1087      })(this);
1088      clearTimeout(this.timeoutID);
1089      return this.timeoutID = setTimeout(callback, time);
1090    }
1091  };
1092
1093  View.prototype.render = function(list) {
1094    var $li, $ul, i, item, len, li, tpl;
1095    if (!($.isArray(list) && list.length > 0)) {
1096      this.hide();
1097      return;
1098    }
1099    this.$el.find('ul').empty();
1100    $ul = this.$el.find('ul');
1101    tpl = this.context.getOpt('displayTpl');
1102    for (i = 0, len = list.length; i < len; i++) {
1103      item = list[i];
1104      item = $.extend({}, item, {
1105        'atwho-at': this.context.at
1106      });
1107      li = this.context.callbacks("tplEval").call(this.context, tpl, item, "onDisplay");
1108      $li = $(this.context.callbacks("highlighter").call(this.context, li, this.context.query.text));
1109      $li.data("item-data", item);
1110      $ul.append($li);
1111    }
1112    this.show();
1113    if (this.context.getOpt('highlightFirst')) {
1114      return $ul.find("li:first").addClass("cur");
1115    }
1116  };
1117
1118  return View;
1119
1120})();
1121
1122var Api;
1123
1124Api = {
1125  load: function(at, data) {
1126    var c;
1127    if (c = this.controller(at)) {
1128      return c.model.load(data);
1129    }
1130  },
1131  isSelecting: function() {
1132    var ref;
1133    return !!((ref = this.controller()) != null ? ref.view.visible() : void 0);
1134  },
1135  hide: function() {
1136    var ref;
1137    return (ref = this.controller()) != null ? ref.view.hide() : void 0;
1138  },
1139  reposition: function() {
1140    var c;
1141    if (c = this.controller()) {
1142      return c.view.reposition(c.rect());
1143    }
1144  },
1145  setIframe: function(iframe, asRoot) {
1146    this.setupRootElement(iframe, asRoot);
1147    return null;
1148  },
1149  run: function() {
1150    return this.dispatch();
1151  },
1152  destroy: function() {
1153    this.shutdown();
1154    return this.$inputor.data('atwho', null);
1155  }
1156};
1157
1158$.fn.atwho = function(method) {
1159  var _args, result;
1160  _args = arguments;
1161  result = null;
1162  this.filter('textarea, input, [contenteditable=""], [contenteditable=true]').each(function() {
1163    var $this, app;
1164    if (!(app = ($this = $(this)).data("atwho"))) {
1165      $this.data('atwho', (app = new App(this)));
1166    }
1167    if (typeof method === 'object' || !method) {
1168      return app.reg(method.at, method);
1169    } else if (Api[method] && app) {
1170      return result = Api[method].apply(app, Array.prototype.slice.call(_args, 1));
1171    } else {
1172      return $.error("Method " + method + " does not exist on jQuery.atwho");
1173    }
1174  });
1175  if (result != null) {
1176    return result;
1177  } else {
1178    return this;
1179  }
1180};
1181
1182$.fn.atwho["default"] = {
1183  at: void 0,
1184  alias: void 0,
1185  data: null,
1186  displayTpl: "<li>${name}</li>",
1187  insertTpl: "${atwho-at}${name}",
1188  headerTpl: null,
1189  callbacks: DEFAULT_CALLBACKS,
1190  functionOverrides: {},
1191  searchKey: "name",
1192  suffix: void 0,
1193  hideWithoutSuffix: false,
1194  startWithSpace: true,
1195  acceptSpaceBar: false,
1196  highlightFirst: true,
1197  limit: 5,
1198  maxLen: 20,
1199  minLen: 0,
1200  displayTimeout: 300,
1201  delay: null,
1202  spaceSelectsMatch: false,
1203  tabSelectsMatch: true,
1204  editableAtwhoQueryAttrs: {},
1205  scrollDuration: 150,
1206  suspendOnComposing: true,
1207  lookUpOnClick: true
1208};
1209
1210$.fn.atwho.debug = false;
1211
1212}));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.