1
- /*! jquery.atwho - v0.4.11 - 2014-04-27
1
+ /*! jquery.atwho - v0.5.0 - 2014-07-14
2
2
* Copyright (c) 2014 chord.luo <chord.luo@gmail.com>;
3
3
* homepage: http://ichord.github.com/At.js
4
4
* Licensed MIT
13
13
}
14
14
} ) ( function ( $ ) {
15
15
16
- var $CONTAINER , Api , App , Atwho , Controller , DEFAULT_CALLBACKS , KEY_CODE , Model , View ,
16
+ var $CONTAINER , Api , App , Controller , DEFAULT_CALLBACKS , KEY_CODE , Model , View ,
17
17
__slice = [ ] . slice ;
18
18
19
19
App = ( function ( ) {
@@ -28,25 +28,36 @@ App = (function() {
28
28
}
29
29
30
30
App . prototype . setIframe = function ( iframe ) {
31
- var error ;
32
31
if ( iframe ) {
33
32
this . window = iframe . contentWindow ;
34
33
this . document = iframe . contentDocument || this . window . document ;
35
- this . iframe = iframe ;
36
- return this ;
34
+ return this . iframe = iframe ;
37
35
} else {
38
- this . document = this . $inputor [ 0 ] . ownerDocument ;
39
- this . window = this . document . defaultView || this . document . parentWindow ;
40
- try {
41
- return this . iframe = this . window . frameElement ;
42
- } catch ( _error ) {
43
- error = _error ;
44
- }
36
+ this . document = document ;
37
+ this . window = window ;
38
+ return this . iframe = null ;
45
39
}
46
40
} ;
47
41
48
42
App . prototype . controller = function ( at ) {
49
- return this . controllers [ this . alias_maps [ at ] || at || this . current_flag ] ;
43
+ var c , current , current_flag , _ref ;
44
+ if ( this . alias_maps [ at ] ) {
45
+ current = this . controllers [ this . alias_maps [ at ] ] ;
46
+ } else {
47
+ _ref = this . controllers ;
48
+ for ( current_flag in _ref ) {
49
+ c = _ref [ current_flag ] ;
50
+ if ( current_flag === at ) {
51
+ current = c ;
52
+ break ;
53
+ }
54
+ }
55
+ }
56
+ if ( current ) {
57
+ return current ;
58
+ } else {
59
+ return this . controllers [ this . current_flag ] ;
60
+ }
50
61
} ;
51
62
52
63
App . prototype . set_context_for = function ( at ) {
@@ -76,15 +87,20 @@ App = (function() {
76
87
} ) ( this ) ) . on ( 'scroll.atwhoInner' , ( function ( _this ) {
77
88
return function ( e ) {
78
89
var _ref ;
79
- return ( _ref = _this . controller ( ) ) != null ? _ref . view . hide ( ) : void 0 ;
90
+ return ( _ref = _this . controller ( ) ) != null ? _ref . view . hide ( e ) : void 0 ;
80
91
} ;
81
92
} ) ( this ) ) . on ( 'blur.atwhoInner' , ( function ( _this ) {
82
93
return function ( e ) {
83
94
var c ;
84
95
if ( c = _this . controller ( ) ) {
85
- return c . view . hide ( c . get_opt ( "display_timeout" ) ) ;
96
+ return c . view . hide ( e , c . get_opt ( "display_timeout" ) ) ;
86
97
}
87
98
} ;
99
+ } ) ( this ) ) . on ( 'click.atwhoInner' , ( function ( _this ) {
100
+ return function ( e ) {
101
+ var _ref ;
102
+ return ( _ref = _this . controller ( ) ) != null ? _ref . view . hide ( e ) : void 0 ;
103
+ } ;
88
104
} ) ( this ) ) ;
89
105
} ;
90
106
@@ -153,7 +169,7 @@ App = (function() {
153
169
switch ( e . keyCode ) {
154
170
case KEY_CODE . ESC :
155
171
e . preventDefault ( ) ;
156
- view . hide ( ) ;
172
+ view . hide ( e ) ;
157
173
break ;
158
174
case KEY_CODE . UP :
159
175
e . preventDefault ( ) ;
@@ -183,7 +199,7 @@ App = (function() {
183
199
return ;
184
200
}
185
201
e . preventDefault ( ) ;
186
- view . choose ( ) ;
202
+ view . choose ( e ) ;
187
203
break ;
188
204
default :
189
205
$ . noop ( ) ;
@@ -274,7 +290,9 @@ Controller = (function() {
274
290
Controller . prototype . catch_query = function ( ) {
275
291
var caret_pos , content , end , query , start , subtext ;
276
292
content = this . content ( ) ;
277
- caret_pos = this . $inputor . caret ( 'pos' ) ;
293
+ caret_pos = this . $inputor . caret ( 'pos' , {
294
+ iframe : this . app . iframe
295
+ } ) ;
278
296
subtext = content . slice ( 0 , caret_pos ) ;
279
297
query = this . callbacks ( "matcher" ) . call ( this , this . at , subtext , this . get_opt ( 'start_with_space' ) ) ;
280
298
if ( typeof query === "string" && query . length <= this . get_opt ( 'max_len' , 20 ) ) {
@@ -296,9 +314,9 @@ Controller = (function() {
296
314
297
315
Controller . prototype . rect = function ( ) {
298
316
var c , scale_bottom ;
299
- if ( ! ( c = this . $inputor . caret ( {
317
+ if ( ! ( c = this . $inputor . caret ( 'offset' , this . pos - 1 , {
300
318
iframe : this . app . iframe
301
- } ) . caret ( 'offset' , this . pos - 1 ) ) ) {
319
+ } ) ) ) {
302
320
return ;
303
321
}
304
322
if ( this . $inputor . attr ( 'contentEditable' ) === 'true' ) {
@@ -344,37 +362,32 @@ Controller = (function() {
344
362
} ;
345
363
346
364
Controller . prototype . insert = function ( content , $li ) {
347
- var $inputor , $insert_node , class_name , content_node , insert_node , pos , range , sel , source , start_str , text ;
365
+ var $inputor , content_node , pos , range , sel , source , start_str , text , wrapped_content ;
348
366
$inputor = this . $inputor ;
349
- if ( $inputor . attr ( 'contentEditable' ) === 'true' ) {
350
- class_name = "atwho-view-flag atwho-view-flag-" + ( this . get_opt ( 'alias' ) || this . at ) ;
351
- content_node = "" + content + "<span contenteditable='false'> <span>" ;
352
- insert_node = "<span contenteditable='false' class='" + class_name + "'>" + content_node + "</span>" ;
353
- $insert_node = $ ( insert_node , this . app . document ) . data ( 'atwho-data-item' , $li . data ( 'item-data' ) ) ;
354
- if ( this . app . document . selection ) {
355
- $insert_node = $ ( "<span contenteditable='true'></span>" , this . app . document ) . html ( $insert_node ) ;
356
- }
357
- }
367
+ wrapped_content = this . callbacks ( 'inserting_wrapper' ) . call ( this , $inputor , content , this . get_opt ( "suffix" ) ) ;
358
368
if ( $inputor . is ( 'textarea, input' ) ) {
359
- content = '' + content ;
360
369
source = $inputor . val ( ) ;
361
370
start_str = source . slice ( 0 , Math . max ( this . query . head_pos - this . at . length , 0 ) ) ;
362
- text = "" + start_str + content + " " + ( source . slice ( this . query [ 'end_pos' ] || 0 ) ) ;
371
+ text = "" + start_str + wrapped_content + ( source . slice ( this . query [ 'end_pos' ] || 0 ) ) ;
363
372
$inputor . val ( text ) ;
364
- $inputor . caret ( 'pos' , start_str . length + content . length + 1 ) ;
373
+ $inputor . caret ( 'pos' , start_str . length + wrapped_content . length , {
374
+ iframe : this . app . iframe
375
+ } ) ;
365
376
} else if ( range = this . range ) {
366
377
pos = range . startOffset - ( this . query . end_pos - this . query . head_pos ) - this . at . length ;
367
378
range . setStart ( range . endContainer , Math . max ( pos , 0 ) ) ;
368
379
range . setEnd ( range . endContainer , range . endOffset ) ;
369
380
range . deleteContents ( ) ;
370
- range . insertNode ( $insert_node [ 0 ] ) ;
381
+ content_node = $ ( wrapped_content , this . app . document ) [ 0 ] ;
382
+ range . insertNode ( content_node ) ;
383
+ range . setEndAfter ( content_node ) ;
371
384
range . collapse ( false ) ;
372
385
sel = this . app . window . getSelection ( ) ;
373
386
sel . removeAllRanges ( ) ;
374
387
sel . addRange ( range ) ;
375
388
} else if ( range = this . ie8_range ) {
376
389
range . moveStart ( 'character' , this . query . end_pos - this . query . head_pos - this . at . length ) ;
377
- range . pasteHTML ( content_node ) ;
390
+ range . pasteHTML ( wrapped_content ) ;
378
391
range . collapse ( false ) ;
379
392
range . select ( ) ;
380
393
}
@@ -504,7 +517,7 @@ View = (function() {
504
517
return $ ( e . currentTarget ) . addClass ( 'cur' ) ;
505
518
} ) . on ( 'click' , ( function ( _this ) {
506
519
return function ( e ) {
507
- _this . choose ( ) ;
520
+ _this . choose ( e ) ;
508
521
return e . preventDefault ( ) ;
509
522
} ;
510
523
} ) ( this ) ) ;
@@ -514,13 +527,16 @@ View = (function() {
514
527
return this . $el . is ( ":visible" ) ;
515
528
} ;
516
529
517
- View . prototype . choose = function ( ) {
530
+ View . prototype . choose = function ( e ) {
518
531
var $li , content ;
519
532
if ( ( $li = this . $el . find ( ".cur" ) ) . length ) {
520
533
content = this . context . insert_content_for ( $li ) ;
521
534
this . context . insert ( this . context . callbacks ( "before_insert" ) . call ( this . context , content , $li ) , $li ) ;
522
- this . context . trigger ( "inserted" , [ $li ] ) ;
523
- return this . hide ( ) ;
535
+ this . context . trigger ( "inserted" , [ $li , e ] ) ;
536
+ this . hide ( e ) ;
537
+ }
538
+ if ( this . context . get_opt ( "hide_without_suffix" ) ) {
539
+ return this . stop_showing = true ;
524
540
}
525
541
} ;
526
542
@@ -562,6 +578,10 @@ View = (function() {
562
578
563
579
View . prototype . show = function ( ) {
564
580
var rect ;
581
+ if ( this . stop_showing ) {
582
+ this . stop_showing = false ;
583
+ return ;
584
+ }
565
585
this . context . mark_range ( ) ;
566
586
if ( ! this . visible ( ) ) {
567
587
this . $el . show ( ) ;
@@ -572,12 +592,15 @@ View = (function() {
572
592
}
573
593
} ;
574
594
575
- View . prototype . hide = function ( time ) {
595
+ View . prototype . hide = function ( e , time ) {
576
596
var callback ;
577
- if ( isNaN ( time && this . visible ( ) ) ) {
597
+ if ( ! this . visible ( ) ) {
598
+ return ;
599
+ }
600
+ if ( isNaN ( time ) ) {
578
601
this . context . reset_rect ( ) ;
579
602
this . $el . hide ( ) ;
580
- return this . context . trigger ( 'hidden' ) ;
603
+ return this . context . trigger ( 'hidden' , [ e ] ) ;
581
604
} else {
582
605
callback = ( function ( _this ) {
583
606
return function ( ) {
@@ -707,13 +730,32 @@ DEFAULT_CALLBACKS = {
707
730
if ( ! query ) {
708
731
return li ;
709
732
}
710
- regexp = new RegExp ( ">\\s*(\\w*)(" + query . replace ( "+" , "\\+" ) + ")(\\w*)\\s*<" , 'ig' ) ;
733
+ regexp = new RegExp ( ">\\s*(\\w*? )(" + query . replace ( "+" , "\\+" ) + ")(\\w*)\\s*<" , 'ig' ) ;
711
734
return li . replace ( regexp , function ( str , $1 , $2 , $3 ) {
712
735
return '> ' + $1 + '<strong>' + $2 + '</strong>' + $3 + ' <' ;
713
736
} ) ;
714
737
} ,
715
738
before_insert : function ( value , $li ) {
716
739
return value ;
740
+ } ,
741
+ inserting_wrapper : function ( $inputor , content , suffix ) {
742
+ var new_suffix , wrapped_content ;
743
+ new_suffix = suffix === "" ? suffix : suffix || " " ;
744
+ if ( $inputor . is ( 'textarea, input' ) ) {
745
+ return '' + content + new_suffix ;
746
+ } else if ( $inputor . attr ( 'contentEditable' ) === 'true' ) {
747
+ new_suffix = suffix === "" ? suffix : suffix || " " ;
748
+ if ( / f i r e f o x / i. test ( navigator . userAgent ) ) {
749
+ wrapped_content = "<span>" + content + new_suffix + "</span>" ;
750
+ } else {
751
+ suffix = "<span contenteditable='false'>" + new_suffix + "<span>" ;
752
+ wrapped_content = "<span contenteditable='false'>" + content + suffix + "</span>" ;
753
+ }
754
+ if ( this . app . document . selection ) {
755
+ wrapped_content = "<span contenteditable='true'>" + content + "</span>" ;
756
+ }
757
+ return wrapped_content ;
758
+ }
717
759
}
718
760
} ;
719
761
@@ -724,36 +766,9 @@ Api = {
724
766
return c . model . load ( data ) ;
725
767
}
726
768
} ,
727
- getInsertedItemsWithIDs : function ( at ) {
728
- var c , ids , items ;
729
- if ( ! ( c = this . controller ( at ) ) ) {
730
- return [ null , null ] ;
731
- }
732
- if ( at ) {
733
- at = "-" + ( c . get_opt ( 'alias' ) || c . at ) ;
734
- }
735
- ids = [ ] ;
736
- items = $ . map ( this . $inputor . find ( "span.atwho-view-flag" + ( at || "" ) ) , function ( item ) {
737
- var data ;
738
- data = $ ( item ) . data ( 'atwho-data-item' ) ;
739
- if ( ids . indexOf ( data . id ) > - 1 ) {
740
- return ;
741
- }
742
- if ( data . id ) {
743
- ids . push = data . id ;
744
- }
745
- return data ;
746
- } ) ;
747
- return [ ids , items ] ;
748
- } ,
749
- getInsertedItems : function ( at ) {
750
- return Api . getInsertedItemsWithIDs . apply ( this , [ at ] ) [ 1 ] ;
751
- } ,
752
- getInsertedIDs : function ( at ) {
753
- return Api . getInsertedItemsWithIDs . apply ( this , [ at ] ) [ 0 ] ;
754
- } ,
755
769
setIframe : function ( iframe ) {
756
- return this . setIframe ( iframe ) ;
770
+ this . setIframe ( iframe ) ;
771
+ return null ;
757
772
} ,
758
773
run : function ( ) {
759
774
return this . dispatch ( ) ;
@@ -764,18 +779,6 @@ Api = {
764
779
}
765
780
} ;
766
781
767
- Atwho = {
768
- init : function ( options ) {
769
- var $this , app ;
770
- app = ( $this = $ ( this ) ) . data ( "atwho" ) ;
771
- if ( ! app ) {
772
- $this . data ( 'atwho' , ( app = new App ( this ) ) ) ;
773
- }
774
- app . reg ( options . at , options ) ;
775
- return this ;
776
- }
777
- } ;
778
-
779
782
$CONTAINER = $ ( "<div id='atwho-container'></div>" ) ;
780
783
781
784
$ . fn . atwho = function ( method ) {
@@ -784,13 +787,14 @@ $.fn.atwho = function(method) {
784
787
$ ( 'body' ) . append ( $CONTAINER ) ;
785
788
result = null ;
786
789
this . filter ( 'textarea, input, [contenteditable=true]' ) . each ( function ( ) {
787
- var app ;
790
+ var $this , app ;
791
+ if ( ! ( app = ( $this = $ ( this ) ) . data ( "atwho" ) ) ) {
792
+ $this . data ( 'atwho' , ( app = new App ( this ) ) ) ;
793
+ }
788
794
if ( typeof method === 'object' || ! method ) {
789
- return Atwho . init . apply ( this , _args ) ;
790
- } else if ( Api [ method ] ) {
791
- if ( app = $ ( this ) . data ( 'atwho' ) ) {
792
- return result = Api [ method ] . apply ( app , Array . prototype . slice . call ( _args , 1 ) ) ;
793
- }
795
+ return app . reg ( method . at , method ) ;
796
+ } else if ( Api [ method ] && app ) {
797
+ return result = Api [ method ] . apply ( app , Array . prototype . slice . call ( _args , 1 ) ) ;
794
798
} else {
795
799
return $ . error ( "Method " + method + " does not exist on jQuery.caret" ) ;
796
800
}
@@ -803,9 +807,11 @@ $.fn.atwho["default"] = {
803
807
alias : void 0 ,
804
808
data : null ,
805
809
tpl : "<li data-value='${atwho-at}${name}'>${name}</li>" ,
806
- insert_tpl : "<span>${atwho-data-value}</span>" ,
810
+ insert_tpl : "<span id='${id}' >${atwho-data-value}</span>" ,
807
811
callbacks : DEFAULT_CALLBACKS ,
808
812
search_key : "name" ,
813
+ suffix : void 0 ,
814
+ hide_without_suffix : false ,
809
815
start_with_space : true ,
810
816
highlight_first : true ,
811
817
limit : 5 ,
0 commit comments