Ghost/ghost/admin/app/mixins/ed-editor-scroll.js

104 lines
3.1 KiB
JavaScript
Raw Normal View History

import Ember from 'ember';
import setScrollClassName from 'ghost/utils/set-scroll-classname';
export default 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.sendAction('updateScrollInfo', 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
}));
},
/**
* once the element has been removed from the DOM unbind from the events which control scroll behaviour
*/
detachScrollHandlers: function () {
this.$().off('keypress');
this.$().off('scroll');
Ember.run.cancel(this.get('scrollThrottle'));
},
didInsertElement: function () {
this._super();
this.attachScrollHandlers();
},
willDestroyElement: function () {
this._super();
this.detachScrollHandlers();
}
});