/** * @provides javelin-behavior-differential-populate * @requires javelin-behavior * javelin-workflow * javelin-util * javelin-dom * javelin-stratcom * javelin-behavior-device * javelin-vector * phabricator-tooltip */ JX.behavior('differential-populate', function(config) { function onresponse(target_id, response) { // As we populate the diff, we try to hold the document scroll position // steady, so that, e.g., users who want to leave a comment on a diff with a // large number of changes don't constantly have the text area scrolled off // the bottom of the screen until the entire diff loads. // // There are two three major cases here: // // - If we're near the top of the document, never scroll. // - If we're near the bottom of the document, always scroll. // - Otherwise, scroll if the changes were above the midline of the // viewport. var target = JX.$(target_id); var old_pos = JX.Vector.getScroll(); var old_view = JX.Vector.getViewport(); var old_dim = JX.Vector.getDocument(); // Number of pixels away from the top or bottom of the document which // count as "nearby". var sticky = 480; var near_top = (old_pos.y <= sticky); var near_bot = ((old_pos.y + old_view.y) >= (old_dim.y - sticky)); var target_pos = JX.Vector.getPos(target); var target_dim = JX.Vector.getDim(target); var target_mid = (target_pos.y + (target_dim.y / 2)); var view_mid = (old_pos.y + (old_view.y / 2)); var above_mid = (target_mid < view_mid); JX.DOM.replace(target, JX.$H(response.changeset)); if (!near_top) { if (near_bot || above_mid) { // Figure out how much taller the document got. var delta = (JX.Vector.getDocument().y - old_dim.y); window.scrollTo(old_pos.x, old_pos.y + delta); } } if (response.coverage) { for (var k in response.coverage) { try { JX.DOM.replace(JX.$(k), JX.$H(response.coverage[k])); } catch (ignored) { // Not terribly important. } } } } // NOTE: If you load the page at one device resolution and then resize to // a different one we don't re-render the diffs, because it's a complicated // mess and you could lose inline comments, cursor positions, etc. var renderer = (JX.Device.getDevice() == 'desktop') ? '2up' : '1up'; // TODO: Once 1up works better, figure out when to show it. renderer = '2up'; for (var k in config.registry) { var data = { ref : config.registry[k], whitespace: config.whitespace, renderer: renderer }; new JX.Workflow(config.uri, data) .setHandler(JX.bind(null, onresponse, k)) .start(); } var highlighted = null; var highlight_class = null; JX.Stratcom.listen( 'click', 'differential-load', function(e) { var meta = e.getNodeData('differential-load'); var diff; try { diff = JX.$(meta.id); } catch (e) { // Already loaded. } if (diff) { JX.DOM.setContent( diff, JX.$H('