Improved checkCursorMenu and checkCursorTag performance and fully rewrite its position method for UX and verified
This commit is contained in:
		
							parent
							
								
									ea703145c5
								
							
						
					
					
						commit
						a55ece023a
					
				| @ -54,7 +54,7 @@ var defaultExtraKeys = { | |||||||
| 
 | 
 | ||||||
| var idleTime = 300000; //5 mins
 | var idleTime = 300000; //5 mins
 | ||||||
| var updateViewDebounce = 200; | var updateViewDebounce = 200; | ||||||
| var cursorMenuThrottle = 100; | var cursorMenuThrottle = 50; | ||||||
| var cursorActivityDebounce = 50; | var cursorActivityDebounce = 50; | ||||||
| var cursorAnimatePeriod = 100; | var cursorAnimatePeriod = 100; | ||||||
| var supportContainers = ['success', 'info', 'warning', 'danger']; | var supportContainers = ['success', 'info', 'warning', 'danger']; | ||||||
| @ -531,6 +531,8 @@ var ui = { | |||||||
|         view: $(".ui-view-area"), |         view: $(".ui-view-area"), | ||||||
|         codemirror: $(".ui-edit-area .CodeMirror"), |         codemirror: $(".ui-edit-area .CodeMirror"), | ||||||
|         codemirrorScroll: $(".ui-edit-area .CodeMirror .CodeMirror-scroll"), |         codemirrorScroll: $(".ui-edit-area .CodeMirror .CodeMirror-scroll"), | ||||||
|  |         codemirrorSizer: $(".ui-edit-area .CodeMirror .CodeMirror-sizer"), | ||||||
|  |         codemirrorSizerInner: $(".ui-edit-area .CodeMirror .CodeMirror-sizer > div"), | ||||||
|         markdown: $(".ui-view-area .markdown-body") |         markdown: $(".ui-view-area .markdown-body") | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| @ -1897,33 +1899,41 @@ function emitUserStatus(force) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function checkCursorTag(coord, ele) { | function checkCursorTag(coord, ele) { | ||||||
|     if (!ele) return; |     if (!ele) return; // return if element not exists
 | ||||||
|     var curosrtagMargin = 60; |     // set margin
 | ||||||
| 	var cursor = editor.getCursor(); |     var tagRightMargin = 0; | ||||||
|     //var viewport = editor.getViewport();
 |     var tagBottomMargin = 2; | ||||||
|     //var viewportHeight = (viewport.to - viewport.from) * editor.defaultTextHeight();
 |     // use sizer to get the real doc size (won't count status bar and gutters)
 | ||||||
|  |     var docWidth = ui.area.codemirrorSizer.width(); | ||||||
|  |     var docHeight = ui.area.codemirrorSizer.height(); | ||||||
|  |     // get editor size (status bar not count in)
 | ||||||
|     var editorWidth = ui.area.codemirror.width(); |     var editorWidth = ui.area.codemirror.width(); | ||||||
|     var editorHeight = ui.area.codemirror.height(); |     var editorHeight = ui.area.codemirror.height(); | ||||||
|     var width = ele.width(); |     // get element size
 | ||||||
|     var height = ele.height(); |     var width = ele.outerWidth(); | ||||||
|     if (!lineHeightMap) |     var height = ele.outerHeight(); | ||||||
|         buildMapInner(); |     var padding = (ele.outerWidth() - ele.width()) / 2; | ||||||
|  |     // get coord position
 | ||||||
|     var left = coord.left; |     var left = coord.left; | ||||||
|     var top = lineHeightMap[cursor.line] * defaultTextHeight; //coord.top;
 |     var top = coord.top; | ||||||
|     top -= ele.closest('.CodeMirror-sizer > *').position().top; |     // get doc top offset (to workaround with viewport)
 | ||||||
|  |     var docTopOffset = ui.area.codemirrorSizerInner.position().top; | ||||||
|  |     // set offset
 | ||||||
|     var offsetLeft = -3; |     var offsetLeft = -3; | ||||||
|     var offsetTop = defaultTextHeight; |     var offsetTop = defaultTextHeight; | ||||||
|     var statusBarHeight = 0; |     // only do when have width and height
 | ||||||
|     if (statusBar) |  | ||||||
|         statusBarHeight = statusBar.outerHeight(); |  | ||||||
|     if (width > 0 && height > 0) { |     if (width > 0 && height > 0) { | ||||||
|         if (left + width + offsetLeft > editorWidth - curosrtagMargin) { |         // flip x when element right bound larger than doc width
 | ||||||
|             offsetLeft = -(width + 10); |         if (left + width + offsetLeft + tagRightMargin > docWidth) { | ||||||
|  |             offsetLeft = -(width + tagRightMargin) + padding + offsetLeft; | ||||||
|         } |         } | ||||||
|         if (top + height + offsetTop > Math.max(editor.doc.height, editorHeight) + curosrtagMargin - statusBarHeight * 2 && top - height > curosrtagMargin) { |         // flip y when element bottom bound larger than doc height
 | ||||||
|             offsetTop = -(height + 4); |         // and element top position is larger than element height
 | ||||||
|  |         if (top + docTopOffset + height + offsetTop + tagBottomMargin > Math.max(editor.doc.height, editorHeight) && top + docTopOffset > height + tagBottomMargin) { | ||||||
|  |             offsetTop = -(height); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     // set position
 | ||||||
|     ele[0].style.left = offsetLeft + 'px'; |     ele[0].style.left = offsetLeft + 'px'; | ||||||
|     ele[0].style.top = offsetTop + 'px'; |     ele[0].style.top = offsetTop + 'px'; | ||||||
| } | } | ||||||
| @ -2464,56 +2474,80 @@ if ($('.cursor-menu').length <= 0) { | |||||||
|     $("<div class='cursor-menu'>").insertAfter('.CodeMirror-cursors'); |     $("<div class='cursor-menu'>").insertAfter('.CodeMirror-cursors'); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | function reverseSortCursorMenu(dropdown) { | ||||||
|  |     var items = dropdown.find('.textcomplete-item'); | ||||||
|  |     items.sort(function (a, b) { | ||||||
|  |         return $(b).attr('data-index') - $(a).attr('data-index'); | ||||||
|  |     }); | ||||||
|  |     return items; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var lastUpSideDown = false; | ||||||
| var upSideDown = false; | var upSideDown = false; | ||||||
| 
 | 
 | ||||||
| var checkCursorMenu = _.throttle(checkCursorMenuInner, cursorMenuThrottle); | var checkCursorMenu = _.throttle(checkCursorMenuInner, cursorMenuThrottle); | ||||||
| 
 | 
 | ||||||
| function checkCursorMenuInner() { | function checkCursorMenuInner() { | ||||||
|     var menuMargin = 60; |     // get element
 | ||||||
|     var dropdown = $('.cursor-menu .dropdown-menu'); |     var dropdown = $('.cursor-menu > .dropdown-menu'); | ||||||
|  |     // return if not exists
 | ||||||
|     if (dropdown.length <= 0) return; |     if (dropdown.length <= 0) return; | ||||||
|  |     // set margin
 | ||||||
|  |     var menuRightMargin = 10; | ||||||
|  |     var menuBottomMargin = 4; | ||||||
|  |     // use sizer to get the real doc size (won't count status bar and gutters)
 | ||||||
|  |     var docWidth = ui.area.codemirrorSizer.width(); | ||||||
|  |     var docHeight = ui.area.codemirrorSizer.height(); | ||||||
|  |     // get editor size (status bar not count in)
 | ||||||
|  |     var editorWidth = ui.area.codemirror.width(); | ||||||
|  |     var editorHeight = ui.area.codemirror.height(); | ||||||
|  |     // get element size
 | ||||||
|  |     var width = dropdown.outerWidth(); | ||||||
|  |     var height = dropdown.outerHeight(); | ||||||
|  |     // get cursor
 | ||||||
|     var cursor = editor.getCursor(); |     var cursor = editor.getCursor(); | ||||||
|     var scrollInfo = editor.getScrollInfo(); |     // set element cursor data
 | ||||||
|     if (!dropdown.hasClass('other-cursor')) |     if (!dropdown.hasClass('other-cursor')) | ||||||
|         dropdown.addClass('other-cursor'); |         dropdown.addClass('other-cursor'); | ||||||
|     dropdown.attr('data-line', cursor.line); |     dropdown.attr('data-line', cursor.line); | ||||||
|     dropdown.attr('data-ch', cursor.ch); |     dropdown.attr('data-ch', cursor.ch); | ||||||
|  |     // get coord position
 | ||||||
|     var coord = editor.charCoords({ |     var coord = editor.charCoords({ | ||||||
|         line: cursor.line, |         line: cursor.line, | ||||||
|         ch: cursor.ch |         ch: cursor.ch | ||||||
|     }, 'windows'); |     }, 'windows'); | ||||||
|     //var viewport = editor.getViewport();
 |  | ||||||
|     //var viewportHeight = (viewport.to - viewport.from) * editor.defaultTextHeight();
 |  | ||||||
|     var editorWidth = ui.area.codemirror.width(); |  | ||||||
|     var editorHeight = ui.area.codemirror.height(); |  | ||||||
|     var width = dropdown.outerWidth(); |  | ||||||
|     var height = dropdown.outerHeight(); |  | ||||||
|     if (!lineHeightMap) |  | ||||||
|         buildMapInner(); |  | ||||||
|     var left = coord.left; |     var left = coord.left; | ||||||
|     var top = lineHeightMap[cursor.line] * defaultTextHeight; //coord.top;
 |     var top = coord.top; | ||||||
|     top -= dropdown.closest('.CodeMirror-sizer > *').position().top; |     // get doc top offset (to workaround with viewport)
 | ||||||
|  |     var docTopOffset = ui.area.codemirrorSizerInner.position().top; | ||||||
|  |     // set offset
 | ||||||
|     var offsetLeft = 0; |     var offsetLeft = 0; | ||||||
|     var offsetTop = defaultTextHeight; |     var offsetTop = defaultTextHeight; | ||||||
|     var statusBarHeight = 0; |     // only do when have width and height
 | ||||||
|     if (statusBar) |     if (width > 0 && height > 0) { | ||||||
|         statusBarHeight = statusBar.outerHeight(); |         // make element right bound not larger than doc width
 | ||||||
|     if (left + width + offsetLeft > editorWidth - menuMargin) |         if (left + width + offsetLeft + menuRightMargin > docWidth) | ||||||
|         offsetLeft = -(left + width - editorWidth + menuMargin); |             offsetLeft = -(left + width - docWidth + menuRightMargin); | ||||||
|     if (top + height + offsetTop > Math.max(editor.doc.height, editorHeight) + menuMargin - statusBarHeight * 2 && top - height > menuMargin) { |         // flip y when element bottom bound larger than doc height
 | ||||||
|         offsetTop = -(height + 4); |         // and element top position is larger than element height
 | ||||||
|  |         if (top + docTopOffset + height + offsetTop + menuBottomMargin > Math.max(editor.doc.height, editorHeight) && top + docTopOffset > height + menuBottomMargin) { | ||||||
|  |             offsetTop = -(height + menuBottomMargin); | ||||||
|  |             // reverse sort menu because upSideDown
 | ||||||
|  |             dropdown.html(reverseSortCursorMenu(dropdown)); | ||||||
|  |             lastUpSideDown = upSideDown; | ||||||
|             upSideDown = true; |             upSideDown = true; | ||||||
|         var items = dropdown.find('.textcomplete-item'); |  | ||||||
|         items.sort(function (a, b) { |  | ||||||
|             return $(b).attr('data-index') - $(a).attr('data-index'); |  | ||||||
|         }); |  | ||||||
|         dropdown.html(items); |  | ||||||
|         dropdown.scrollTop(dropdown[0].scrollHeight); |  | ||||||
|         } else { |         } else { | ||||||
|  |             lastUpSideDown = upSideDown; | ||||||
|             upSideDown = false; |             upSideDown = false; | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  |     // make menu scroll top only if upSideDown changed
 | ||||||
|  |     if (upSideDown !== lastUpSideDown) | ||||||
|  |         dropdown.scrollTop(dropdown[0].scrollHeight); | ||||||
|  |     // set element offset data
 | ||||||
|     dropdown.attr('data-offset-left', offsetLeft); |     dropdown.attr('data-offset-left', offsetLeft); | ||||||
|     dropdown.attr('data-offset-top', offsetTop); |     dropdown.attr('data-offset-top', offsetTop); | ||||||
|  |     // set position
 | ||||||
|     dropdown[0].style.left = left + offsetLeft + 'px'; |     dropdown[0].style.left = left + offsetLeft + 'px'; | ||||||
|     dropdown[0].style.top = top + offsetTop + 'px'; |     dropdown[0].style.top = top + offsetTop + 'px'; | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user