mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 22:43:30 +03:00
95 lines
3.0 KiB
JavaScript
95 lines
3.0 KiB
JavaScript
|
import Ember from 'ember';
|
||
|
|
||
|
import setScrollClassName from 'ghost/utils/set-scroll-classname';
|
||
|
|
||
|
var EditorScroll = Ember.Mixin.create({
|
||
|
/**
|
||
|
* Determine if the cursor is at the end of the textarea
|
||
|
*/
|
||
|
isCursorAtEnd: function () {
|
||
|
var selection = this.$().getSelection(),
|
||
|
value = this.getValue(),
|
||
|
linesAtEnd = 3,
|
||
|
stringAfterCursor,
|
||
|
match;
|
||
|
|
||
|
stringAfterCursor = value.substring(selection.end);
|
||
|
/* jscs: disable */
|
||
|
match = stringAfterCursor.match(/\n/g);
|
||
|
/* jscs: enable */
|
||
|
|
||
|
if (!match || match.length < linesAtEnd) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Build an object that represents the scroll state
|
||
|
*/
|
||
|
getScrollInfo: function () {
|
||
|
var scroller = this.get('element'),
|
||
|
scrollInfo = {
|
||
|
top: scroller.scrollTop,
|
||
|
height: scroller.scrollHeight,
|
||
|
clientHeight: scroller.clientHeight,
|
||
|
diff: scroller.scrollHeight - scroller.clientHeight,
|
||
|
padding: 50,
|
||
|
isCursorAtEnd: this.isCursorAtEnd()
|
||
|
};
|
||
|
|
||
|
return scrollInfo;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Calculate if we're within scrollInfo.padding of the end of the document, and scroll the rest of the way
|
||
|
*/
|
||
|
adjustScrollPosition: function () {
|
||
|
// If we're receiving change events from the end of the document, i.e the user is typing-at-the-end, update the
|
||
|
// scroll position to ensure both panels stay in view and in sync
|
||
|
var scrollInfo = this.getScrollInfo();
|
||
|
if (scrollInfo.isCursorAtEnd && (scrollInfo.diff >= scrollInfo.top) &&
|
||
|
(scrollInfo.diff < scrollInfo.top + scrollInfo.padding)) {
|
||
|
scrollInfo.top += scrollInfo.padding;
|
||
|
// Scroll the left pane
|
||
|
this.$().scrollTop(scrollInfo.top);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Send the scrollInfo for scrollEvents to the view so that the preview pane can be synced
|
||
|
*/
|
||
|
scrollHandler: function () {
|
||
|
this.set('scrollThrottle', Ember.run.throttle(this, function () {
|
||
|
this.set('scrollInfo', this.getScrollInfo());
|
||
|
}, 10));
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* once the element is in the DOM bind to the events which control scroll behaviour
|
||
|
*/
|
||
|
attachScrollHandlers: function () {
|
||
|
var $el = this.$();
|
||
|
|
||
|
$el.on('keypress', Ember.run.bind(this, this.adjustScrollPosition));
|
||
|
|
||
|
$el.on('scroll', Ember.run.bind(this, this.scrollHandler));
|
||
|
$el.on('scroll', Ember.run.bind($el, setScrollClassName, {
|
||
|
target: Ember.$('.js-entry-markdown'),
|
||
|
offset: 10
|
||
|
}));
|
||
|
}.on('didInsertElement'),
|
||
|
|
||
|
/**
|
||
|
* once the element is in the DOM unbind from the events which control scroll behaviour
|
||
|
*/
|
||
|
detachScrollHandlers: function () {
|
||
|
this.$().off('keypress');
|
||
|
this.$().off('scroll');
|
||
|
Ember.run.cancel(this.get('scrollThrottle'));
|
||
|
}.on('willDestroyElement')
|
||
|
});
|
||
|
|
||
|
export default EditorScroll;
|