Browse Source

Implement synchronous scrolling in demo

pull/14/head
Alex Kocharin 10 years ago
parent
commit
9faf0adefb
  1. 104
      demo/assets/index.js

104
demo/assets/index.js

@ -1,7 +1,7 @@
(function () {
'use strict';
var mdHtml, mdSrc, permalink;
var mdHtml, mdSrc, permalink, scrollMap;
var defaults = {
html: false, // Enable HTML tags in source
@ -63,6 +63,24 @@
mdHtml.renderer.rules.table_open = function () {
return '<table class="table table-striped">\n';
};
mdHtml.renderer.rules.paragraph_open = function (tokens, idx) {
var line;
if (tokens[idx].lines && tokens[idx].level === 0) {
line = tokens[idx].lines[0];
return '<p class="line" data-line="' + line + '">';
}
return '<p>';
};
mdHtml.renderer.rules.heading_open = function (tokens, idx) {
var line;
if (tokens[idx].lines && tokens[idx].level === 0) {
line = tokens[idx].lines[0];
return '<h' + tokens[idx].hLevel + ' class="line" data-line="' + line + '">';
}
return '<h' + tokens[idx].hLevel + '>';
};
}
function updateResult() {
@ -70,6 +88,7 @@
$('.result-html').html(mdHtml.render(source));
$('.result-src-content').html(window.hljs.highlight('html', mdSrc.render(source)).value);
scrollMap = null;
var dump = JSON.stringify(mdSrc.parse(source, { references: {} }), null, 2);
$('.result-debug-content').html(window.hljs.highlight('json', dump).value);
@ -89,6 +108,88 @@
}
}
function recomputeScroll() {
var i, offset, nonEmptyList, pos, a, b, lineHeightMap, linesCount,
acc, sourceLikeDiv, textarea = $('.source');
sourceLikeDiv = $('<div />').css({
position: 'absolute',
visibility: 'hidden',
height: 'auto',
width: textarea[0].clientWidth,
'font-size': textarea.css('font-size'),
'font-family': textarea.css('font-family'),
'line-height': textarea.css('line-height'),
'white-space': textarea.css('white-space')
}).appendTo('body');
offset = $('.result-html').scrollTop() - $('.result-html').offset().top;
scrollMap = [];
nonEmptyList = [];
lineHeightMap = [];
acc = 0;
textarea.val().split('\n').forEach(function(str) {
var h, lh;
lineHeightMap.push(acc);
if (str.length === 0) {
acc++;
return;
}
sourceLikeDiv.text(str);
h = parseFloat(sourceLikeDiv.css('height'));
lh = parseFloat(sourceLikeDiv.css('line-height'));
acc += Math.round(h / lh);
});
sourceLikeDiv.remove();
lineHeightMap.push(acc);
linesCount = acc;
for (i = 0; i < linesCount; i++) { scrollMap.push(-1); }
nonEmptyList.push(0);
scrollMap[0] = 0;
$('.line').each(function(n, el) {
var $el = $(el), t = $el.data('line');
if (t === '') { return; }
t = lineHeightMap[t];
if (t !== 0) { nonEmptyList.push(t); }
scrollMap[t] = Math.round($el.offset().top + offset);
});
nonEmptyList.push(linesCount);
scrollMap[linesCount] = $('.result-html')[0].scrollHeight;
pos = 0;
for (i = 1; i < linesCount; i++) {
if (scrollMap[i] !== -1) {
pos++;
continue;
}
a = nonEmptyList[pos];
b = nonEmptyList[pos + 1];
scrollMap[i] = Math.round((scrollMap[b] * (i - a) + scrollMap[a] * (b - i)) / (b - a));
}
return scrollMap;
}
function syncScroll() {
var textarea = $('.source'),
lineHeight = parseFloat(textarea.css('line-height')),
lineNo;
lineNo = Math.floor(textarea.scrollTop() / lineHeight);
if (!scrollMap) { recomputeScroll(); }
$('.result-html').stop(true).animate({
scrollTop: scrollMap[lineNo]
}, 100, 'linear');
}
$(function() {
// highlight snippet
@ -180,6 +281,7 @@
// Setup listeners
$('.source').on('keyup paste cut mouseup', updateResult);
$('.source').on('scroll', _.debounce(syncScroll, 50, { maxWait: 50 }));
$('.source-clear').on('click', function (event) {
$('.source').val('');

Loading…
Cancel
Save