refactor: Extract scroll_util.js.

We now use scroll_element_into_container() in two different
places, so it's worth extracting.
This commit is contained in:
Steve Howell 2018-04-24 12:09:16 +00:00 committed by Tim Abbott
parent 068e4bf32b
commit 97b9367d20
8 changed files with 122 additions and 118 deletions

View File

@ -108,6 +108,7 @@
"Socket": false,
"channel": false,
"components": false,
"scroll_util": false,
"message_viewport": false,
"upload_widget": false,
"avatar": false,

View File

@ -55,7 +55,7 @@ set_global('keydown_util', {
set_global('compose_state', {});
set_global('stream_list', {
set_global('scroll_util', {
scroll_element_into_container: () => {},
});

View File

@ -0,0 +1,55 @@
zrequire('scroll_util');
(function test_scroll_delta() {
// If we are entirely on-screen, don't scroll
assert.equal(0, scroll_util.scroll_delta({
elem_top: 1,
elem_bottom: 9,
container_height: 10,
}));
assert.equal(0, scroll_util.scroll_delta({
elem_top: -5,
elem_bottom: 15,
container_height: 10,
}));
// The top is offscreen.
assert.equal(-3, scroll_util.scroll_delta({
elem_top: -3,
elem_bottom: 5,
container_height: 10,
}));
assert.equal(-3, scroll_util.scroll_delta({
elem_top: -3,
elem_bottom: -1,
container_height: 10,
}));
assert.equal(-11, scroll_util.scroll_delta({
elem_top: -150,
elem_bottom: -1,
container_height: 10,
}));
// The bottom is offscreen.
assert.equal(3, scroll_util.scroll_delta({
elem_top: 7,
elem_bottom: 13,
container_height: 10,
}));
assert.equal(3, scroll_util.scroll_delta({
elem_top: 11,
elem_bottom: 13,
container_height: 10,
}));
assert.equal(11, scroll_util.scroll_delta({
elem_top: 11,
elem_bottom: 99,
container_height: 10,
}));
}());

View File

@ -13,6 +13,7 @@ zrequire('hash_util');
zrequire('narrow');
zrequire('unread');
zrequire('stream_data');
zrequire('scroll_util');
zrequire('stream_list');
var noop = function () {};
@ -237,7 +238,7 @@ function initialize_stream_data() {
topic_list.rebuild = noop;
topic_list.active_stream_id = noop;
stream_list.show_all_streams = noop;
stream_list.scroll_element_into_container = noop;
scroll_util.scroll_element_into_container = noop;
var scrollbar_updated = false;
@ -671,57 +672,3 @@ var keydown_handler = $('.stream-list-filter').get_on_handler('keydown');
assert.equal(html_dict.get(1000), '<div>stub-html-devel');
assert.equal(html_dict.get(5000), '<div>stub-html-Denmark');
}());
(function test_scroll_delta() {
// If we are entirely on-screen, don't scroll
assert.equal(0, stream_list.scroll_delta({
elem_top: 1,
elem_bottom: 9,
container_height: 10,
}));
assert.equal(0, stream_list.scroll_delta({
elem_top: -5,
elem_bottom: 15,
container_height: 10,
}));
// The top is offscreen.
assert.equal(-3, stream_list.scroll_delta({
elem_top: -3,
elem_bottom: 5,
container_height: 10,
}));
assert.equal(-3, stream_list.scroll_delta({
elem_top: -3,
elem_bottom: -1,
container_height: 10,
}));
assert.equal(-11, stream_list.scroll_delta({
elem_top: -150,
elem_bottom: -1,
container_height: 10,
}));
// The bottom is offscreen.
assert.equal(3, stream_list.scroll_delta({
elem_top: 7,
elem_bottom: 13,
container_height: 10,
}));
assert.equal(3, stream_list.scroll_delta({
elem_top: 11,
elem_bottom: 13,
container_height: 10,
}));
assert.equal(11, stream_list.scroll_delta({
elem_top: 11,
elem_bottom: 99,
container_height: 10,
}));
}());

View File

@ -61,9 +61,7 @@ var list_cursor = function (opts) {
};
self.adjust_scroll = function (li) {
// TODO: move scroll_element_into_container out of
// stream_list.js
stream_list.scroll_element_into_container(li, opts.list.container);
scroll_util.scroll_element_into_container(li, opts.list.container);
};
self.redraw = function () {

59
static/js/scroll_util.js Normal file
View File

@ -0,0 +1,59 @@
var scroll_util = (function () {
var exports = {};
exports.scroll_delta = function (opts) {
var elem_top = opts.elem_top;
var container_height = opts.container_height;
var elem_bottom = opts.elem_bottom;
var delta = 0;
if (elem_top < 0) {
delta = Math.max(
elem_top,
elem_bottom - container_height
);
delta = Math.min(0, delta);
} else {
if (elem_bottom > container_height) {
delta = Math.min(
elem_top,
elem_bottom - container_height
);
delta = Math.max(0, delta);
}
}
return delta;
};
exports.scroll_element_into_container = function (elem, container) {
// This does the minimum amount of scrolling that is needed to make
// the element visible. It doesn't try to center the element, so
// this will be non-intrusive to users when they already have
// the element visible.
var elem_top = elem.position().top;
var elem_bottom = elem_top + elem.height();
var opts = {
elem_top: elem_top,
elem_bottom: elem_bottom,
container_height: container.height(),
};
var delta = exports.scroll_delta(opts);
if (delta === 0) {
return;
}
container.scrollTop(container.scrollTop() + delta);
};
return exports;
}());
if (typeof module !== 'undefined') {
module.exports = scroll_util;
}

View File

@ -622,7 +622,7 @@ function keydown_arrow_key(dir_up, all_streams_selector, scroll_container) {
current_sel.removeClass('highlighted_stream');
next_sibling.addClass('highlighted_stream');
exports.scroll_element_into_container(next_sibling, scroll_container);
scroll_util.scroll_element_into_container(next_sibling, scroll_container);
}
}
@ -692,64 +692,7 @@ exports.scroll_stream_into_view = function (stream_li) {
return;
}
exports.scroll_element_into_container(stream_li, container);
};
exports.scroll_delta = function (opts) {
var elem_top = opts.elem_top;
var container_height = opts.container_height;
var elem_bottom = opts.elem_bottom;
var delta = 0;
if (elem_top < 0) {
delta = Math.max(
elem_top,
elem_bottom - container_height
);
delta = Math.min(0, delta);
} else {
if (elem_bottom > container_height) {
delta = Math.min(
elem_top,
elem_bottom - container_height
);
delta = Math.max(0, delta);
}
}
return delta;
};
exports.scroll_element_into_container = function (elem, container) {
// This is a generic function to make elem visible in
// container by scrolling container appropriately. We may want to
// eventually move this into another module, but I couldn't find
// an ideal landing space for this. I considered a few modules, but
// some are already kind of bloated (ui.js), some may be deprecated
// (scroll_bar.js), and some just aren't exact fits (resize.js).
//
// This does the minimum amount of scrolling that is needed to make
// the element visible. It doesn't try to center the element, so
// this will be non-intrusive to users when they already have
// the element visible.
var elem_top = elem.position().top;
var elem_bottom = elem_top + elem.height();
var opts = {
elem_top: elem_top,
elem_bottom: elem_bottom,
container_height: container.height(),
};
var delta = exports.scroll_delta(opts);
if (delta === 0) {
return;
}
container.scrollTop(container.scrollTop() + delta);
scroll_util.scroll_element_into_container(stream_li, container);
};
return exports;

View File

@ -1038,6 +1038,7 @@ JS_SPECS = {
'js/lightbox_canvas.js',
'js/rtl.js',
'js/dict.js',
'js/scroll_util.js',
'js/components.js',
'js/localstorage.js',
'js/drafts.js',