|
|
|
@ -2,15 +2,14 @@
|
|
|
|
|
|
|
|
|
|
define('navigator', ['forum/pagination', 'components'], function (pagination, components) {
|
|
|
|
|
var navigator = {};
|
|
|
|
|
var index = 1;
|
|
|
|
|
var index = 0;
|
|
|
|
|
var count = 0;
|
|
|
|
|
var navigatorUpdateTimeoutId;
|
|
|
|
|
|
|
|
|
|
var touchTooltipEl;
|
|
|
|
|
var touchIntervalId;
|
|
|
|
|
var renderPostIntervalId;
|
|
|
|
|
var touchX;
|
|
|
|
|
var touchY;
|
|
|
|
|
var touchIndex;
|
|
|
|
|
var renderPostIndex;
|
|
|
|
|
var isNavigating = false;
|
|
|
|
|
var firstMove = true;
|
|
|
|
|
|
|
|
|
@ -20,13 +19,14 @@ define('navigator', ['forum/pagination', 'components'], function (pagination, co
|
|
|
|
|
var paginationTextEl = paginationBlockEl.find('.pagination-text');
|
|
|
|
|
var paginationBlockMeterEl = paginationBlockEl.find('meter');
|
|
|
|
|
var paginationBlockProgressEl = paginationBlockEl.find('.progress-bar');
|
|
|
|
|
var thumb;
|
|
|
|
|
|
|
|
|
|
$(window).on('action:ajaxify.start', function () {
|
|
|
|
|
$(window).off('keydown', onKeyDown);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
navigator.init = function (selector, count, toTop, toBottom, callback) {
|
|
|
|
|
index = 1;
|
|
|
|
|
index = 0;
|
|
|
|
|
navigator.selector = selector;
|
|
|
|
|
navigator.callback = callback;
|
|
|
|
|
navigator.toTop = toTop || function () {};
|
|
|
|
@ -37,6 +37,8 @@ define('navigator', ['forum/pagination', 'components'], function (pagination, co
|
|
|
|
|
paginationBlockMeterEl = paginationBlockEl.find('meter');
|
|
|
|
|
paginationBlockProgressEl = paginationBlockEl.find('.progress-bar');
|
|
|
|
|
|
|
|
|
|
thumb = $('.scroller-thumb');
|
|
|
|
|
|
|
|
|
|
$(window).off('scroll', navigator.delayedUpdate).on('scroll', navigator.delayedUpdate);
|
|
|
|
|
|
|
|
|
|
paginationBlockEl.find('.dropdown-menu').off('click').on('click', function (e) {
|
|
|
|
@ -69,76 +71,184 @@ define('navigator', ['forum/pagination', 'components'], function (pagination, co
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$('.pagination-block.visible-xs').on('touchstart', function (e) {
|
|
|
|
|
touchTooltipEl = $('.navigator-thumb');
|
|
|
|
|
touchX = Math.min($(window).width(), Math.max(0, e.touches[0].clientX));
|
|
|
|
|
touchY = Math.min($(window).height(), Math.max(0, e.touches[0].clientY));
|
|
|
|
|
if (ajaxify.data.template.topic) {
|
|
|
|
|
handleScrollNav();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handleKeys();
|
|
|
|
|
|
|
|
|
|
navigator.setCount(count);
|
|
|
|
|
navigator.update(0);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function clampTop(newTop) {
|
|
|
|
|
var parent = thumb.parent();
|
|
|
|
|
var parentOffset = parent.offset();
|
|
|
|
|
if (newTop < parentOffset.top) {
|
|
|
|
|
newTop = parentOffset.top;
|
|
|
|
|
} else if (newTop > parentOffset.top + parent.height() - thumb.height()) {
|
|
|
|
|
newTop = parentOffset.top + parent.height() - thumb.height();
|
|
|
|
|
}
|
|
|
|
|
return newTop;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setThumbToIndex(index) {
|
|
|
|
|
if (!thumb.length || thumb.is(':hidden')) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var parent = thumb.parent();
|
|
|
|
|
var thumbText = thumb.find('.thumb-text');
|
|
|
|
|
var parentOffset = parent.offset();
|
|
|
|
|
var percent = (index - 1) / ajaxify.data.postcount;
|
|
|
|
|
if (index === count) {
|
|
|
|
|
percent = 1;
|
|
|
|
|
}
|
|
|
|
|
var newTop = clampTop(parentOffset.top + ((parent.height() - thumb.height()) * percent));
|
|
|
|
|
|
|
|
|
|
var offset = { top: newTop, left: thumb.offset().left };
|
|
|
|
|
thumb.offset(offset);
|
|
|
|
|
thumbText.text(index + '/' + ajaxify.data.postcount);
|
|
|
|
|
renderPost(index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleScrollNav() {
|
|
|
|
|
if (!thumb.length) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var thumbText = thumb.find('.thumb-text');
|
|
|
|
|
var thumbHeight = thumb.height();
|
|
|
|
|
var thumbHalfHeight = thumbHeight / 2;
|
|
|
|
|
var parent = thumb.parent();
|
|
|
|
|
var parentHeight = parent.height();
|
|
|
|
|
var mouseDragging = false;
|
|
|
|
|
$(window).on('action:ajaxify.end', function () {
|
|
|
|
|
renderPostIndex = null;
|
|
|
|
|
});
|
|
|
|
|
$('.pagination-block .dropdown-menu').parent().on('shown.bs.dropdown', function () {
|
|
|
|
|
setThumbToIndex(index);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
thumb.on('mousedown', function () {
|
|
|
|
|
mouseDragging = true;
|
|
|
|
|
$(window).on('mousemove', mousemove);
|
|
|
|
|
firstMove = true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function mouseup() {
|
|
|
|
|
$(window).off('mousemove', mousemove);
|
|
|
|
|
if (mouseDragging) {
|
|
|
|
|
navigator.scrollToIndex(index - 1, true, 0);
|
|
|
|
|
paginationBlockEl.find('[data-toggle="dropdown"]').trigger('click');
|
|
|
|
|
}
|
|
|
|
|
clearRenderInterval();
|
|
|
|
|
mouseDragging = false;
|
|
|
|
|
firstMove = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function mousemove(ev) {
|
|
|
|
|
var newTop = clampTop(ev.pageY - thumbHalfHeight);
|
|
|
|
|
var parentOffset = parent.offset();
|
|
|
|
|
|
|
|
|
|
var offset = { top: newTop, left: thumb.offset().left };
|
|
|
|
|
thumb.offset(offset);
|
|
|
|
|
|
|
|
|
|
var percent = (newTop - parentOffset.top) / (parentHeight - thumbHeight);
|
|
|
|
|
index = Math.max(1, Math.ceil(ajaxify.data.postcount * percent));
|
|
|
|
|
navigator.updateTextAndProgressBar();
|
|
|
|
|
thumbText.text(index + '/' + ajaxify.data.postcount);
|
|
|
|
|
if (firstMove) {
|
|
|
|
|
delayedRenderPost();
|
|
|
|
|
}
|
|
|
|
|
firstMove = false;
|
|
|
|
|
ev.stopPropagation();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function delayedRenderPost() {
|
|
|
|
|
clearRenderInterval();
|
|
|
|
|
renderPostIntervalId = setInterval(function () {
|
|
|
|
|
renderPost(index);
|
|
|
|
|
}, 250);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$(window).off('mousemove', mousemove);
|
|
|
|
|
$(window).off('mouseup', mouseup).on('mouseup', mouseup);
|
|
|
|
|
|
|
|
|
|
thumb.on('touchstart', function (ev) {
|
|
|
|
|
isNavigating = true;
|
|
|
|
|
touchX = Math.min($(window).width(), Math.max(0, ev.touches[0].clientX));
|
|
|
|
|
touchY = Math.min($(window).height(), Math.max(0, ev.touches[0].clientY));
|
|
|
|
|
firstMove = true;
|
|
|
|
|
}).on('touchmove', function (e) {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
thumb.on('touchmove', function (ev) {
|
|
|
|
|
var windowWidth = $(window).width();
|
|
|
|
|
var windowHeight = $(window).height();
|
|
|
|
|
var deltaX = Math.abs(touchX - Math.min(windowWidth, Math.max(0, e.touches[0].clientX)));
|
|
|
|
|
var deltaY = Math.abs(touchY - Math.min(windowHeight, Math.max(0, e.touches[0].clientY)));
|
|
|
|
|
touchX = Math.min(windowWidth, Math.max(0, e.touches[0].clientX));
|
|
|
|
|
touchY = Math.min(windowHeight, Math.max(0, e.touches[0].clientY));
|
|
|
|
|
if (deltaX >= deltaY && firstMove) {
|
|
|
|
|
var deltaX = Math.abs(touchX - Math.min(windowWidth, Math.max(0, ev.touches[0].clientX)));
|
|
|
|
|
var deltaY = Math.abs(touchY - Math.min(windowHeight, Math.max(0, ev.touches[0].clientY)));
|
|
|
|
|
touchX = Math.min(windowWidth, Math.max(0, ev.touches[0].clientX));
|
|
|
|
|
touchY = Math.min(windowHeight, Math.max(0, ev.touches[0].clientY));
|
|
|
|
|
|
|
|
|
|
if (deltaY >= deltaX && firstMove) {
|
|
|
|
|
isNavigating = true;
|
|
|
|
|
touchIntervalId = setInterval(updateTooltip, 100);
|
|
|
|
|
delayedRenderPost();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isNavigating) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
var percent = touchX / windowWidth;
|
|
|
|
|
ev.preventDefault();
|
|
|
|
|
ev.stopPropagation();
|
|
|
|
|
var newTop = clampTop(touchY + $(window).scrollTop() - thumbHalfHeight);
|
|
|
|
|
var parentOffset = thumb.parent().offset();
|
|
|
|
|
var offset = { top: newTop, left: thumb.offset().left };
|
|
|
|
|
thumb.offset(offset);
|
|
|
|
|
|
|
|
|
|
var percent = (newTop - parentOffset.top) / (parentHeight - thumbHeight);
|
|
|
|
|
index = Math.max(1, Math.ceil(count * percent));
|
|
|
|
|
index = index > count ? count : index;
|
|
|
|
|
|
|
|
|
|
thumbText.text(index + '/' + ajaxify.data.postcount);
|
|
|
|
|
|
|
|
|
|
if (firstMove) {
|
|
|
|
|
updateTooltip(function () {
|
|
|
|
|
touchTooltipEl.removeClass('hidden');
|
|
|
|
|
});
|
|
|
|
|
renderPost(index);
|
|
|
|
|
}
|
|
|
|
|
navigator.updateTextAndProgressBar();
|
|
|
|
|
}
|
|
|
|
|
firstMove = false;
|
|
|
|
|
}).on('touchend', function () {
|
|
|
|
|
if (touchIntervalId) {
|
|
|
|
|
clearInterval(touchIntervalId);
|
|
|
|
|
touchIntervalId = 0;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
thumb.on('touchend', function () {
|
|
|
|
|
clearRenderInterval();
|
|
|
|
|
if (isNavigating) {
|
|
|
|
|
touchTooltipEl.addClass('hidden');
|
|
|
|
|
navigator.scrollToIndex(index - 1, true, 0);
|
|
|
|
|
isNavigating = false;
|
|
|
|
|
paginationBlockEl.find('[data-toggle="dropdown"]').trigger('click');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handleKeys();
|
|
|
|
|
|
|
|
|
|
navigator.setCount(count);
|
|
|
|
|
navigator.update(0);
|
|
|
|
|
};
|
|
|
|
|
function clearRenderInterval() {
|
|
|
|
|
if (renderPostIntervalId) {
|
|
|
|
|
clearInterval(renderPostIntervalId);
|
|
|
|
|
renderPostIntervalId = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateTooltip(callback) {
|
|
|
|
|
function renderPost(index, callback) {
|
|
|
|
|
callback = callback || function () {};
|
|
|
|
|
if (touchIndex === index) {
|
|
|
|
|
if (renderPostIndex === index || paginationBlockEl.find('.post-content').is(':hidden')) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
touchIndex = index;
|
|
|
|
|
touchTooltipEl.css({ left: Math.min($(window).width() - touchTooltipEl.outerWidth(), Math.max(touchX - (touchTooltipEl.outerWidth() / 2), 0)) });
|
|
|
|
|
renderPostIndex = index;
|
|
|
|
|
|
|
|
|
|
socket.emit('posts.getTimestampByIndex', { tid: ajaxify.data.tid, index: index - 1 }, function (err, timestamp) {
|
|
|
|
|
socket.emit('posts.getPostSummaryByIndex', { tid: ajaxify.data.tid, index: index - 1 }, function (err, postData) {
|
|
|
|
|
if (err) {
|
|
|
|
|
return app.alertError(err.message);
|
|
|
|
|
}
|
|
|
|
|
app.parseAndTranslate('partials/topic/navigation-post', { post: postData }, function (html) {
|
|
|
|
|
html.find('.timeago').timeago();
|
|
|
|
|
paginationBlockEl.find('.post-content').html(html);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var date = new Date(timestamp);
|
|
|
|
|
var ds = date.toLocaleString(config.userLang, { month: 'long' });
|
|
|
|
|
touchTooltipEl.find('.text').translateText('[[global:pagination.out_of, ' + index + ', ' + count + ']]');
|
|
|
|
|
if (timestamp > Date.now() - (30 * 24 * 60 * 60 * 1000)) {
|
|
|
|
|
touchTooltipEl.find('.time').text(ds + ' ' + date.getDate());
|
|
|
|
|
} else {
|
|
|
|
|
touchTooltipEl.find('.time').text(ds + ' ' + date.getFullYear());
|
|
|
|
|
}
|
|
|
|
|
callback();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
@ -171,7 +281,11 @@ define('navigator', ['forum/pagination', 'components'], function (pagination, co
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
navigator.setCount = function (value) {
|
|
|
|
|
count = parseInt(value, 10);
|
|
|
|
|
value = parseInt(value, 10);
|
|
|
|
|
if (value === count) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
count = value;
|
|
|
|
|
navigator.updateTextAndProgressBar();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -213,10 +327,10 @@ define('navigator', ['forum/pagination', 'components'], function (pagination, co
|
|
|
|
|
a spot where a user is expecting to begin reading.
|
|
|
|
|
*/
|
|
|
|
|
threshold = typeof threshold === 'number' ? threshold : undefined;
|
|
|
|
|
|
|
|
|
|
var newIndex = index;
|
|
|
|
|
var els = $(navigator.selector);
|
|
|
|
|
if (els.length) {
|
|
|
|
|
index = parseInt(els.first().attr('data-index'), 10) + 1;
|
|
|
|
|
newIndex = parseInt(els.first().attr('data-index'), 10) + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var scrollTop = $(window).scrollTop();
|
|
|
|
@ -235,7 +349,7 @@ define('navigator', ['forum/pagination', 'components'], function (pagination, co
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (distanceToMiddle < previousDistance) {
|
|
|
|
|
index = elIndex + 1;
|
|
|
|
|
newIndex = elIndex + 1;
|
|
|
|
|
previousDistance = distanceToMiddle;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -245,13 +359,13 @@ define('navigator', ['forum/pagination', 'components'], function (pagination, co
|
|
|
|
|
var nearBottom = scrollTop + windowHeight > documentHeight - 100 && parseInt(els.last().attr('data-index'), 10) === count - 1;
|
|
|
|
|
|
|
|
|
|
if (atTop) {
|
|
|
|
|
index = 1;
|
|
|
|
|
newIndex = 1;
|
|
|
|
|
} else if (nearBottom) {
|
|
|
|
|
index = count;
|
|
|
|
|
newIndex = count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If a threshold is undefined, try to determine one based on new index
|
|
|
|
|
if (threshold === undefined && ajaxify.data.template.topic === true) {
|
|
|
|
|
if (threshold === undefined && ajaxify.data.template.topic) {
|
|
|
|
|
if (atTop) {
|
|
|
|
|
threshold = 0;
|
|
|
|
|
} else {
|
|
|
|
@ -264,10 +378,15 @@ define('navigator', ['forum/pagination', 'components'], function (pagination, co
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (typeof navigator.callback === 'function') {
|
|
|
|
|
navigator.callback(index, count, threshold);
|
|
|
|
|
navigator.callback(newIndex, count, threshold);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (newIndex !== index) {
|
|
|
|
|
index = newIndex;
|
|
|
|
|
navigator.updateTextAndProgressBar();
|
|
|
|
|
setThumbToIndex(index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
navigator.updateTextAndProgressBar();
|
|
|
|
|
toggle(!!count);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -422,7 +541,7 @@ define('navigator', ['forum/pagination', 'components'], function (pagination, co
|
|
|
|
|
|
|
|
|
|
var scrollTop = 0;
|
|
|
|
|
if (postHeight < viewportHeight) {
|
|
|
|
|
scrollTop = (scrollTo.offset().top - (viewportHeight / 2) + (postHeight / 2)) - topicHeaderHeight;
|
|
|
|
|
scrollTop = (scrollTo.offset().top - (viewportHeight / 2) + (postHeight)) - topicHeaderHeight;
|
|
|
|
|
} else {
|
|
|
|
|
scrollTop = scrollTo.offset().top - navbarHeight - topicHeaderHeight;
|
|
|
|
|
}
|
|
|
|
|