@@ -196,21 +196,6 @@ EmojiTooltip.prototype.onMouseLeave = function (triggerUnshow) {
196
196
}
197
197
} ;
198
198
199
- EmojiTooltip . prototype . getScrollWidth = function ( ) {
200
- var outer = $ ( '<div>' ) . css ( {
201
- position : 'absolute' ,
202
- width : 100 ,
203
- height : 100 ,
204
- overflow : 'scroll' ,
205
- top : - 9999
206
- } ) . appendTo ( $ ( document . body ) ) ;
207
-
208
- var scrollbarWidth = outer [ 0 ] . offsetWidth - outer [ 0 ] . clientWidth ;
209
- outer . remove ( ) ;
210
-
211
- return scrollbarWidth ;
212
- } ;
213
-
214
199
215
200
216
201
EmojiTooltip . prototype . createTooltip = function ( ) {
@@ -219,20 +204,12 @@ EmojiTooltip.prototype.createTooltip = function () {
219
204
}
220
205
221
206
var self = this ;
222
- this . tooltipEl = $ ( '<div class="composer_emoji_tooltip noselect"><div class="composer_emoji_tooltip_tabs"></div><div class="composer_emoji_tooltip_content_wrap nano mobile_scrollable_wrap"><div class="composer_emoji_tooltip_content nano-content clearfix"></div></div><div class="composer_emoji_tooltip_footer"><a class="composer_emoji_tooltip_settings"></a></div><div class="composer_emoji_tooltip_tail"><i class="icon icon-tooltip-tail"></i></div></div>' ) . appendTo ( document . body ) ;
223
-
224
- this . tabsEl = $ ( '.composer_emoji_tooltip_tabs' , this . tooltip ) ;
225
- this . contentWrapEl = $ ( '.composer_emoji_tooltip_content_wrap' , this . tooltip ) ;
226
- this . contentEl = $ ( '.composer_emoji_tooltip_content' , this . tooltip ) ;
227
- this . footerEl = $ ( '.composer_emoji_tooltip_footer' , this . tooltip ) ;
228
- this . settingsEl = $ ( '.composer_emoji_tooltip_settings' , this . tooltip ) ;
229
-
230
- var scrollWidth = this . getScrollWidth ( ) ;
231
- if ( scrollWidth > 0 ) {
232
- this . tooltipEl . css ( {
233
- width : parseInt ( this . tooltipEl . css ( 'width' ) ) + scrollWidth
234
- } ) ;
235
- }
207
+ this . tooltipEl = $ ( '<div class="composer_emoji_tooltip noselect"><div class="composer_emoji_tooltip_tabs"></div><div class="composer_emoji_tooltip_content clearfix"></div><div class="composer_emoji_tooltip_footer"><a class="composer_emoji_tooltip_settings"></a></div><div class="composer_emoji_tooltip_tail"><i class="icon icon-tooltip-tail"></i></div></div>' ) . appendTo ( document . body ) ;
208
+
209
+ this . tabsEl = $ ( '.composer_emoji_tooltip_tabs' , this . tooltipEl ) ;
210
+ this . contentEl = $ ( '.composer_emoji_tooltip_content' , this . tooltipEl ) ;
211
+ this . footerEl = $ ( '.composer_emoji_tooltip_footer' , this . tooltipEl ) ;
212
+ this . settingsEl = $ ( '.composer_emoji_tooltip_settings' , this . tooltipEl ) ;
236
213
237
214
angular . forEach ( [ 'recent' , 'smile' , 'flower' , 'bell' , 'car' , 'grid' , 'stickers' ] , function ( tabName , tabIndex ) {
238
215
var tab = $ ( '<a class="composer_emoji_tooltip_tab composer_emoji_tooltip_tab_' + tabName + '"></a>' )
@@ -254,9 +231,7 @@ EmojiTooltip.prototype.createTooltip = function () {
254
231
}
255
232
} ) ;
256
233
257
- if ( ! Config . Mobile ) {
258
- this . contentWrapEl . nanoScroller ( { preventPageScrolling : true , tabIndex : - 1 } ) ;
259
- }
234
+ this . scroller = new Scroller ( this . contentEl , { classPrefix : 'composer_emoji_tooltip' } ) ;
260
235
261
236
this . contentEl . on ( 'mousedown' , function ( e ) {
262
237
e = e . originalEvent || e ;
@@ -323,13 +298,7 @@ EmojiTooltip.prototype.updateTabContents = function () {
323
298
324
299
var renderContent = function ( ) {
325
300
self . contentEl . html ( html . join ( '' ) ) ;
326
-
327
- if ( ! Config . Mobile ) {
328
- self . contentWrapEl . nanoScroller ( { scroll : 'top' } ) ;
329
- setTimeout ( function ( ) {
330
- self . contentWrapEl . nanoScroller ( ) ;
331
- } , 100 ) ;
332
- }
301
+ self . scroller . reinit ( ) ;
333
302
}
334
303
335
304
if ( this . tab == 6 ) { // Stickers
@@ -488,12 +457,9 @@ function MessageComposer (textarea, options) {
488
457
this . setUpInput ( ) ;
489
458
490
459
this . autoCompleteWrapEl = $ ( '<div class="composer_dropdown_wrap"></div>' ) . appendTo ( document . body ) ;
491
- this . autoCompleteScrollerEl = $ ( '<div class="composer_dropdown_scroller nano"></div>' ) . appendTo ( this . autoCompleteWrapEl ) ;
492
- this . autoCompleteEl = $ ( '<ul class="composer_dropdown dropdown-menu nano-content"></ul>' ) . appendTo ( this . autoCompleteScrollerEl ) ;
460
+ this . autoCompleteEl = $ ( '<ul class="composer_dropdown dropdown-menu"></ul>' ) . appendTo ( this . autoCompleteWrapEl ) ;
493
461
494
- if ( ! Config . Mobile ) {
495
- this . autoCompleteScrollerEl . nanoScroller ( { preventPageScrolling : true , tabIndex : - 1 } ) ;
496
- }
462
+ this . scroller = new Scroller ( this . autoCompleteEl , { maxHeight : 180 } ) ;
497
463
498
464
var self = this ;
499
465
this . autoCompleteEl . on ( 'mousedown' , function ( e ) {
@@ -614,18 +580,14 @@ MessageComposer.prototype.onKeyEvent = function (e) {
614
580
currentSelected . removeClass ( 'composer_autocomplete_option_active' ) ;
615
581
if ( nextWrap ) {
616
582
$ ( nextWrap ) . find ( 'a' ) . addClass ( 'composer_autocomplete_option_active' ) ;
617
- if ( ! Config . Mobile ) {
618
- scrollToNode ( this . autoCompleteEl [ 0 ] , nextWrap , this . autoCompleteScrollerEl ) ;
619
- }
583
+ this . scroller . scrollToNode ( nextWrap ) ;
620
584
return cancelEvent ( e ) ;
621
585
}
622
586
}
623
587
624
588
var childNodes = this . autoCompleteEl [ 0 ] . childNodes ;
625
589
var nextWrap = childNodes [ next ? 0 : childNodes . length - 1 ] ;
626
- if ( ! Config . Mobile ) {
627
- scrollToNode ( this . autoCompleteEl [ 0 ] , nextWrap , this . autoCompleteScrollerEl ) ;
628
- }
590
+ this . scroller . scrollToNode ( nextWrap ) ;
629
591
$ ( nextWrap ) . find ( 'a' ) . addClass ( 'composer_autocomplete_option_active' ) ;
630
592
631
593
return cancelEvent ( e ) ;
@@ -714,7 +676,7 @@ MessageComposer.prototype.restoreSelection = function () {
714
676
715
677
716
678
717
- MessageComposer . prototype . checkAutocomplete = function ( ) {
679
+ MessageComposer . prototype . checkAutocomplete = function ( forceFull ) {
718
680
if ( Config . Mobile ) {
719
681
return false ;
720
682
}
@@ -730,7 +692,9 @@ MessageComposer.prototype.checkAutocomplete = function () {
730
692
var value = textarea . value ;
731
693
}
732
694
733
- value = value . substr ( 0 , pos ) ;
695
+ if ( ! forceFull ) {
696
+ value = value . substr ( 0 , pos ) ;
697
+ }
734
698
735
699
var matches = value . match ( this . autoCompleteRegEx ) ;
736
700
if ( matches ) {
@@ -1096,15 +1060,7 @@ MessageComposer.prototype.focus = function () {
1096
1060
MessageComposer . prototype . renderSuggestions = function ( html ) {
1097
1061
this . autoCompleteEl . html ( html . join ( '' ) ) ;
1098
1062
this . autoCompleteWrapEl . show ( ) ;
1099
-
1100
- var self = this ;
1101
- if ( ! Config . Mobile ) {
1102
- self . autoCompleteScrollerEl . nanoScroller ( { scroll : 'top' } ) ;
1103
- setTimeout ( function ( ) {
1104
- self . autoCompleteScrollerEl . nanoScroller ( ) ;
1105
- } , 100 ) ;
1106
- }
1107
-
1063
+ this . scroller . reinit ( ) ;
1108
1064
this . updatePosition ( ) ;
1109
1065
this . autocompleteShown = true ;
1110
1066
}
@@ -1161,7 +1117,7 @@ MessageComposer.prototype.showCommandsSuggestions = function (commands) {
1161
1117
1162
1118
for ( i = 0 ; i < count ; i ++ ) {
1163
1119
command = commands [ i ] ;
1164
- html . push ( '<li><a class="composer_command_option" data-command="' + encodeEntities ( command . value ) + '"><span class="composer_user_photo" data-user-id="' + command . botID + '"></span><span class="composer_command_value">' + encodeEntities ( command . value ) + '</span><span class="composer_command_desc">' + encodeEntities ( command . description ) + '</span></a></li>' ) ;
1120
+ html . push ( '<li><a class="composer_command_option" data-command="' + encodeEntities ( command . value ) + '"><span class="composer_user_photo" data-user-id="' + command . botID + '"></span><span class="composer_command_value">' + encodeEntities ( command . value ) + '</span><span class="composer_command_desc">' + command . rDescription + '</span></a></li>' ) ;
1165
1121
}
1166
1122
1167
1123
this . renderSuggestions ( html ) ;
@@ -1182,14 +1138,13 @@ MessageComposer.prototype.showCommandsSuggestions = function (commands) {
1182
1138
MessageComposer . prototype . updatePosition = function ( ) {
1183
1139
var offset = ( this . richTextareaEl || this . textareaEl ) . offset ( ) ;
1184
1140
var width = ( this . richTextareaEl || this . textareaEl ) . outerWidth ( ) ;
1185
- var contentHeight = this . autoCompleteEl [ 0 ] . firstChild . clientHeight * this . autoCompleteEl [ 0 ] . childNodes . length ;
1186
- var height = Math . min ( 180 , contentHeight ) ;
1141
+ var height = this . scroller . updateHeight ( ) ;
1187
1142
this . autoCompleteWrapEl . css ( {
1188
1143
top : offset . top - height ,
1189
1144
left : offset . left ,
1190
- width : width - 2 ,
1191
- height : height
1145
+ width : width - 2
1192
1146
} ) ;
1147
+ this . scroller . update ( ) ;
1193
1148
}
1194
1149
1195
1150
MessageComposer . prototype . hideSuggestions = function ( ) {
@@ -1202,3 +1157,83 @@ MessageComposer.prototype.resetTyping = function () {
1202
1157
this . lastLength = 0 ;
1203
1158
}
1204
1159
1160
+
1161
+
1162
+ function Scroller ( content , options ) {
1163
+ options = options || { } ;
1164
+ var classPrefix = options . classPrefix || 'scroller' ;
1165
+
1166
+ this . content = $ ( content ) ;
1167
+ this . content . wrap ( '<div class="' + classPrefix + '_scrollable_container"><div class="' + classPrefix + '_scrollable_wrap"><div class="' + classPrefix + '_scrollable"></div></div></div>' ) ;
1168
+
1169
+ this . scrollable = $ ( this . content [ 0 ] . parentNode ) ;
1170
+ this . scroller = $ ( this . scrollable [ 0 ] . parentNode ) ;
1171
+ this . wrap = $ ( this . scroller [ 0 ] . parentNode ) ;
1172
+
1173
+ this . useNano = options . nano !== undefined ? options . nano : ! Config . Mobile ;
1174
+ this . maxHeight = options . maxHeight ;
1175
+
1176
+ if ( this . useNano ) {
1177
+ this . scrollable . addClass ( 'nano-content' ) ;
1178
+ this . scroller . addClass ( 'nano' ) ;
1179
+ this . scroller . nanoScroller ( { preventPageScrolling : true , tabIndex : - 1 } ) ;
1180
+ } else {
1181
+ if ( this . maxHeight ) {
1182
+ this . wrap . css ( { maxHeight : this . maxHeight } ) ;
1183
+ }
1184
+ }
1185
+ this . updateHeight ( ) ;
1186
+ }
1187
+
1188
+ Scroller . prototype . update = function ( ) {
1189
+ if ( this . useNano ) {
1190
+ $ ( this . scroller ) . nanoScroller ( ) ;
1191
+ }
1192
+ }
1193
+
1194
+ Scroller . prototype . reinit = function ( ) {
1195
+ this . scrollTo ( 0 ) ;
1196
+ if ( this . useNano ) {
1197
+ setTimeout ( ( function ( ) {
1198
+ this . updateHeight ( ) ;
1199
+ } ) . bind ( this ) , 100 )
1200
+ }
1201
+ }
1202
+
1203
+ Scroller . prototype . updateHeight = function ( ) {
1204
+ var height ;
1205
+ if ( this . maxHeight ) {
1206
+ var contentHeight = this . content [ 0 ] . offsetHeight ;
1207
+ height = Math . min ( this . maxHeight , contentHeight ) ;
1208
+ this . wrap . css ( { height : height } ) ;
1209
+ } else {
1210
+ height = this . scroller [ 0 ] . offsetHeight ;
1211
+ }
1212
+ $ ( this . scroller ) . nanoScroller ( ) ;
1213
+ return height ;
1214
+ }
1215
+
1216
+
1217
+ Scroller . prototype . scrollTo = function ( scrollTop ) {
1218
+ this . scrollable [ 0 ] . scrollTop = scrollTop ;
1219
+ if ( this . useNano ) {
1220
+ $ ( this . scroller ) . nanoScroller ( { flash : true } ) ;
1221
+ }
1222
+ }
1223
+
1224
+ Scroller . prototype . scrollToNode = function ( node ) {
1225
+ node = node [ 0 ] || node ;
1226
+ var elTop = node . offsetTop - 15 ,
1227
+ elHeight = node . offsetHeight + 30 ,
1228
+ scrollTop = this . scrollable [ 0 ] . scrollTop ,
1229
+ viewportHeight = this . scrollable [ 0 ] . clientHeight ;
1230
+
1231
+ if ( scrollTop > elTop ) { // we are below the node to scroll
1232
+ this . scrollTo ( elTop ) ;
1233
+ }
1234
+ else if ( scrollTop < elTop + elHeight - viewportHeight ) { // we are over the node to scroll
1235
+ this . scrollTo ( elTop + elHeight - viewportHeight ) ;
1236
+ }
1237
+ }
1238
+
1239
+
0 commit comments