Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14474962
D11472.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
20 KB
Referenced Files
None
Subscribers
None
D11472.diff
View Options
diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -7,7 +7,7 @@
*/
return array(
'names' => array(
- 'core.pkg.css' => 'd7209022',
+ 'core.pkg.css' => '4517260e',
'core.pkg.js' => '2d9bfc06',
'darkconsole.pkg.js' => '8ab24e01',
'differential.pkg.css' => '8af45893',
@@ -39,7 +39,7 @@
'rsrc/css/application/base/main-menu-view.css' => '3cf893a9',
'rsrc/css/application/base/notification-menu.css' => '6aa0a74b',
'rsrc/css/application/base/phabricator-application-launch-view.css' => '5d71008f',
- 'rsrc/css/application/base/standard-page-view.css' => '2c96cfb5',
+ 'rsrc/css/application/base/standard-page-view.css' => '98cc4c75',
'rsrc/css/application/chatlog/chatlog.css' => '852140ff',
'rsrc/css/application/config/config-options.css' => '7fedf08b',
'rsrc/css/application/config/config-template.css' => '25d446d6',
@@ -104,14 +104,15 @@
'rsrc/css/application/slowvote/slowvote.css' => '266df6a1',
'rsrc/css/application/tokens/tokens.css' => '3d0f239e',
'rsrc/css/application/uiexample/example.css' => '528b19de',
- 'rsrc/css/core/core.css' => 'ca42b69f',
+ 'rsrc/css/core/core.css' => 'd7f6ec35',
'rsrc/css/core/remarkup.css' => '0ee3d256',
'rsrc/css/core/syntax.css' => '56c1ba38',
- 'rsrc/css/core/z-index.css' => '27a9a1be',
+ 'rsrc/css/core/z-index.css' => 'a39e6f5a',
'rsrc/css/diviner/diviner-shared.css' => '38813222',
'rsrc/css/font/font-awesome.css' => '0c10d96b',
'rsrc/css/font/font-source-sans-pro.css' => '91d53463',
'rsrc/css/font/phui-font-icon-base.css' => '3dad2ae3',
+ 'rsrc/css/layout/phabricator-crumbs-view.css' => 'd5aa87e4',
'rsrc/css/layout/phabricator-filetree-view.css' => 'fccf9f82',
'rsrc/css/layout/phabricator-hovercard-view.css' => '893f4783',
'rsrc/css/layout/phabricator-side-menu-view.css' => '7e8c6341',
@@ -124,7 +125,6 @@
'rsrc/css/phui/phui-action-list.css' => '9ee9910a',
'rsrc/css/phui/phui-box.css' => '7b3a2eed',
'rsrc/css/phui/phui-button.css' => '008ba5e2',
- 'rsrc/css/phui/phui-crumbs-view.css' => '1705bce6',
'rsrc/css/phui/phui-document.css' => 'bbeb1890',
'rsrc/css/phui/phui-feed-story.css' => '582f0ec9',
'rsrc/css/phui/phui-fontkit.css' => '9c3d2dce',
@@ -152,7 +152,7 @@
'rsrc/css/sprite-gradient.css' => '4bdb98a7',
'rsrc/css/sprite-login.css' => 'a355d921',
'rsrc/css/sprite-main-header.css' => '92720ee2',
- 'rsrc/css/sprite-menu.css' => '661b879f',
+ 'rsrc/css/sprite-menu.css' => '0ca5a908',
'rsrc/css/sprite-projects.css' => 'b0d9e24f',
'rsrc/css/sprite-tokens.css' => '1706b943',
'rsrc/externals/font/fontawesome/fontawesome-webfont.eot' => '579d3140',
@@ -199,6 +199,7 @@
'rsrc/externals/javelin/lib/Resource.js' => '44959b73',
'rsrc/externals/javelin/lib/Routable.js' => 'b3e7d692',
'rsrc/externals/javelin/lib/Router.js' => '29274e2b',
+ 'rsrc/externals/javelin/lib/Scrollbar.js' => '5dd3e41b',
'rsrc/externals/javelin/lib/URI.js' => '6eff08aa',
'rsrc/externals/javelin/lib/Vector.js' => 'cc1bd0b0',
'rsrc/externals/javelin/lib/WebSocket.js' => '3f840822',
@@ -414,7 +415,7 @@
'rsrc/js/application/releeph/releeph-request-typeahead.js' => 'de2e896f',
'rsrc/js/application/repository/repository-crossreference.js' => 'f9539603',
'rsrc/js/application/search/behavior-reorder-queries.js' => 'e9581f08',
- 'rsrc/js/application/slowvote/behavior-slowvote-embed.js' => 'd6f54db0',
+ 'rsrc/js/application/slowvote/behavior-slowvote-embed.js' => '887ad43f',
'rsrc/js/application/transactions/behavior-show-older-transactions.js' => 'bde958eb',
'rsrc/js/application/transactions/behavior-transaction-comment-form.js' => '9f7309fb',
'rsrc/js/application/transactions/behavior-transaction-list.js' => '13c739ea',
@@ -476,6 +477,7 @@
'rsrc/js/core/behavior-remarkup-preview.js' => 'f7379f45',
'rsrc/js/core/behavior-reorder-applications.js' => '76b9fc3e',
'rsrc/js/core/behavior-reveal-content.js' => '60821bc7',
+ 'rsrc/js/core/behavior-scrollbar.js' => '77607b63',
'rsrc/js/core/behavior-search-typeahead.js' => '724b1247',
'rsrc/js/core/behavior-select-on-click.js' => '4e3e79a6',
'rsrc/js/core/behavior-toggle-class.js' => 'e566f52c',
@@ -641,9 +643,10 @@
'javelin-behavior-reorder-applications' => '76b9fc3e',
'javelin-behavior-reorder-columns' => 'e1d25dfb',
'javelin-behavior-repository-crossreference' => 'f9539603',
+ 'javelin-behavior-scrollbar' => '77607b63',
'javelin-behavior-search-reorder-queries' => 'e9581f08',
'javelin-behavior-select-on-click' => '4e3e79a6',
- 'javelin-behavior-slowvote-embed' => 'd6f54db0',
+ 'javelin-behavior-slowvote-embed' => '887ad43f',
'javelin-behavior-stripe-payment-form' => '3f5d6dbf',
'javelin-behavior-test-payment-form' => 'fc91ab6c',
'javelin-behavior-toggle-class' => 'e566f52c',
@@ -670,6 +673,7 @@
'javelin-resource' => '44959b73',
'javelin-routable' => 'b3e7d692',
'javelin-router' => '29274e2b',
+ 'javelin-scrollbar' => '5dd3e41b',
'javelin-stratcom' => '8b0ad945',
'javelin-tokenizer' => '7644823e',
'javelin-typeahead' => '70baed2f',
@@ -705,8 +709,9 @@
'phabricator-busy' => '6453c869',
'phabricator-chatlog-css' => '852140ff',
'phabricator-content-source-view-css' => '4b8b05d4',
- 'phabricator-core-css' => 'ca42b69f',
+ 'phabricator-core-css' => 'd7f6ec35',
'phabricator-countdown-css' => '86b7b0a0',
+ 'phabricator-crumbs-view-css' => 'd5aa87e4',
'phabricator-dashboard-css' => 'a2bfdcbf',
'phabricator-drag-and-drop-file-upload' => '8c49f386',
'phabricator-draggable-list' => 'a16ec1c6',
@@ -734,7 +739,7 @@
'phabricator-side-menu-view-css' => '7e8c6341',
'phabricator-slowvote-css' => '266df6a1',
'phabricator-source-code-view-css' => '7d346aa4',
- 'phabricator-standard-page-view' => '2c96cfb5',
+ 'phabricator-standard-page-view' => '98cc4c75',
'phabricator-textareautils' => '5c93c52c',
'phabricator-title' => '5c1c758c',
'phabricator-tooltip' => '1d298e3a',
@@ -750,7 +755,7 @@
'phabricator-uiexample-reactor-select' => 'a155550f',
'phabricator-uiexample-reactor-sendclass' => '1def2711',
'phabricator-uiexample-reactor-sendproperties' => 'b1f0ccee',
- 'phabricator-zindex-css' => '27a9a1be',
+ 'phabricator-zindex-css' => 'a39e6f5a',
'phame-css' => '19ecc703',
'pholio-css' => '95174bdd',
'pholio-edit-css' => '3ad9d1ee',
@@ -767,7 +772,6 @@
'phui-calendar-day-css' => 'de035c8a',
'phui-calendar-list-css' => 'c1d0ca59',
'phui-calendar-month-css' => 'a92e47d2',
- 'phui-crumbs-view-css' => '1705bce6',
'phui-document-view-css' => 'bbeb1890',
'phui-feed-story-css' => '582f0ec9',
'phui-font-icon-base-css' => '3dad2ae3',
@@ -815,7 +819,7 @@
'sprite-gradient-css' => '4bdb98a7',
'sprite-login-css' => 'a355d921',
'sprite-main-header-css' => '92720ee2',
- 'sprite-menu-css' => '661b879f',
+ 'sprite-menu-css' => '0ca5a908',
'sprite-projects-css' => 'b0d9e24f',
'sprite-tokens-css' => '1706b943',
'syntax-highlighting-css' => '56c1ba38',
@@ -1206,6 +1210,12 @@
'javelin-dom',
'javelin-vector',
),
+ '5dd3e41b' => array(
+ 'javelin-install',
+ 'javelin-dom',
+ 'javelin-stratcom',
+ 'javelin-vector',
+ ),
'5fefb143' => array(
'javelin-behavior',
'javelin-dom',
@@ -1328,6 +1338,10 @@
'javelin-reactor',
'javelin-util',
),
+ '77607b63' => array(
+ 'javelin-behavior',
+ 'javelin-scrollbar',
+ ),
'7814b593' => array(
'javelin-request',
'javelin-behavior',
@@ -1425,6 +1439,12 @@
'javelin-view-interpreter',
'javelin-view-renderer',
),
+ '887ad43f' => array(
+ 'javelin-behavior',
+ 'javelin-request',
+ 'javelin-stratcom',
+ 'javelin-dom',
+ ),
'8a41885b' => array(
'javelin-install',
'javelin-dom',
@@ -1729,12 +1749,6 @@
'javelin-dom',
'javelin-stratcom',
),
- 'd6f54db0' => array(
- 'javelin-behavior',
- 'javelin-request',
- 'javelin-stratcom',
- 'javelin-dom',
- ),
'd75709e6' => array(
'javelin-behavior',
'javelin-workflow',
@@ -2007,7 +2021,7 @@
'phabricator-filetree-view-css',
'phabricator-nav-view-css',
'phabricator-side-menu-view-css',
- 'phui-crumbs-view-css',
+ 'phabricator-crumbs-view-css',
'phui-object-item-list-view-css',
'global-drag-and-drop-css',
'phui-spacing-css',
diff --git a/src/view/page/PhabricatorStandardPageView.php b/src/view/page/PhabricatorStandardPageView.php
--- a/src/view/page/PhabricatorStandardPageView.php
+++ b/src/view/page/PhabricatorStandardPageView.php
@@ -340,10 +340,16 @@
}
}
- return phutil_tag(
+ Javelin::initBehavior(
+ 'scrollbar',
+ array(
+ 'nodeID' => 'phabricator-standard-page',
+ ));
+
+ $main_page = phutil_tag(
'div',
array(
- 'id' => 'base-page',
+ 'id' => 'phabricator-standard-page',
'class' => 'phabricator-standard-page',
),
array(
@@ -356,6 +362,15 @@
$this->renderFooter(),
)),
));
+
+ return phutil_tag(
+ 'div',
+ array(
+ 'class' => 'main-page-frame',
+ ),
+ array(
+ $main_page,
+ ));
}
protected function getTail() {
diff --git a/webroot/rsrc/css/application/base/standard-page-view.css b/webroot/rsrc/css/application/base/standard-page-view.css
--- a/webroot/rsrc/css/application/base/standard-page-view.css
+++ b/webroot/rsrc/css/application/base/standard-page-view.css
@@ -112,3 +112,73 @@
display: inline-block;
margin: 2px 2px -2px 0;
}
+
+.main-page-frame {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ right: 0;
+ left: 0;
+ overflow: hidden;
+}
+
+.jx-scrollbar-frame {
+ position: relative;
+ height: 100%;
+ overflow: hidden;
+}
+
+.jx-scrollbar-viewport {
+ position: absolute;
+ overflow-x: hidden;
+ overflow-y: scroll;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+}
+
+.jx-scrollbar-test {
+ position: absolute;
+ left: -300px;
+}
+
+.jx-scrollbar-bar {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 7px;
+ width: 11px;
+}
+
+.jx-scrollbar-bar .jx-scrollbar-handle {
+ position: absolute;
+ right: 2px;
+ -webkit-border-radius: 7px;
+ -moz-border-radius: 7px;
+ border-radius: 7px;
+ min-height: 10px;
+ width: 7px;
+ opacity: 0;
+ -webkit-transition: opacity 0.2s linear;
+ -moz-transition: opacity 0.2s linear;
+ -o-transition: opacity 0.2s linear;
+ -ms-transition: opacity 0.2s linear;
+ transition: opacity 0.2s linear;
+ background: #6c6e71;
+ -webkit-background-clip: padding-box;
+ -moz-background-clip: padding;
+}
+
+.jx-scrollbar-bar:hover .jx-scrollbar-handle {
+ opacity: 0.7;
+ -webkit-transition: opacity 0 linear;
+ -moz-transition: opacity 0 linear;
+ -o-transition: opacity 0 linear;
+ -ms-transition: opacity 0 linear;
+ transition: opacity 0 linear;
+}
+
+.jx-scrollbar-bar .jx-scrollbar-visible {
+ opacity: 0.7;
+}
diff --git a/webroot/rsrc/css/core/core.css b/webroot/rsrc/css/core/core.css
--- a/webroot/rsrc/css/core/core.css
+++ b/webroot/rsrc/css/core/core.css
@@ -2,16 +2,6 @@
* @provides phabricator-core-css
*/
-body {
- /* Always show the vertical scrollbar so that going from a page without a
- scrollbar to a page with a scrollbar doesn't make content jump a few
- pixels left when the viewport narrows. */
- overflow-y: scroll;
- /* reset behavior in ie7, as it will add an extra scrollbar regardless
- selector * targets ie6 and ie7 only */
- *overflow-y: auto;
-}
-
.device-phone {
/* By default, the iPhone zooms all text on the page by some percentage when
you rotate from portrait mode to landscape mode. Disable this, since it
diff --git a/webroot/rsrc/css/core/z-index.css b/webroot/rsrc/css/core/z-index.css
--- a/webroot/rsrc/css/core/z-index.css
+++ b/webroot/rsrc/css/core/z-index.css
@@ -129,6 +129,10 @@
z-index: 17;
}
+.jx-scrollbar {
+ z-index: 18;
+}
+
.pholio-device-lightbox {
z-index: 20;
}
diff --git a/webroot/rsrc/externals/javelin/lib/Scrollbar.js b/webroot/rsrc/externals/javelin/lib/Scrollbar.js
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/externals/javelin/lib/Scrollbar.js
@@ -0,0 +1,273 @@
+/**
+ * @provides javelin-scrollbar
+ * @requires javelin-install
+ * javelin-dom
+ * javelin-stratcom
+ * javelin-vector
+ * @javelin
+ */
+
+/**
+ * Provides an aesthetic scrollbar.
+ *
+ * This shoves an element's scrollbar under a hidden overflow and draws a
+ * pretty looking fake one in its place. This makes complex UIs with multiple
+ * independently scrollable panels less hideous by (a) making the scrollbar
+ * itself prettier and (b) reclaiming the space occupied by the scrollbar.
+ *
+ * Note that on OSX the heavy scrollbars are normally drawn only if you have
+ * a mouse connected. OSX uses more aesthetic touchpad scrollbars normally,
+ * which these scrollbars emulate.
+ *
+ * This class was initially adapted from "Trackpad Scroll Emulator", by
+ * Jonathan Nicol. See <https://github.com/jnicol/trackpad-scroll-emulator>.
+ */
+JX.install('Scrollbar', {
+
+ construct: function(frame) {
+ // Wrap the frame content in a bunch of nodes. The frame itself stays on
+ // the outside so that any positioning information the node had isn't
+ // disrupted.
+
+ // We put a "viewport" node inside of it, which is what actually scrolls.
+ // This is the node that gets a scrollbar, but we make the viewport very
+ // slightly too wide for the frame. That hides the scrollbar underneath
+ // the edge of the frame.
+
+ // We put a "content" node inside of the viewport. This allows us to
+ // measure the content height so we can resize and offset the scrollbar
+ // handle properly.
+
+ // We move all the actual frame content into the "content" node. So it
+ // ends up wrapped by the "content" node, then by the "viewport" node,
+ // and finally by the original "frame" node.
+
+ JX.DOM.alterClass(frame, 'jx-scrollbar-frame', true);
+
+ var content = JX.$N('div', {className: 'jx-scrollbar-content'});
+ while (frame.firstChild) {
+ JX.DOM.appendContent(content, frame.firstChild);
+ }
+
+ var viewport = JX.$N('div', {className: 'jx-scrollbar-viewport'}, content);
+ JX.DOM.appendContent(frame, viewport);
+
+ this._frame = frame;
+ this._viewport = viewport;
+ this._content = content;
+
+ // The handle is the visible node which you can click and drag.
+ this._handle = JX.$N('div', {className: 'jx-scrollbar-handle'});
+
+ // The bar is the area the handle slides up and down in.
+ this._bar = JX.$N('div', {className: 'jx-scrollbar-bar'}, this._handle);
+
+ JX.DOM.prependContent(frame, this._bar);
+
+ JX.DOM.listen(this._handle, 'mousedown', null, JX.bind(this, this._ondrag));
+ JX.DOM.listen(this._bar, 'mousedown', null, JX.bind(this, this._onjump));
+
+ JX.enableDispatch(document.body, 'mouseenter');
+ JX.enableDispatch(document.body, 'mousemove');
+
+ JX.DOM.listen(viewport, 'mouseenter', null, JX.bind(this, this._onenter));
+ JX.DOM.listen(frame, 'scroll', null, JX.bind(this, this._onscroll));
+
+ JX.DOM.listen(viewport, 'mouseenter', null, JX.bind(this, this._onenter));
+ JX.DOM.listen(viewport, 'mouseenter', null, JX.bind(this, this._onenter));
+
+ JX.Stratcom.listen('mousemove', null, JX.bind(this, this._onmove));
+ JX.Stratcom.listen('mouseup', null, JX.bind(this, this._ondrop));
+ JX.Stratcom.listen('resize', null, JX.bind(this, this._onresize));
+
+ this._resizeViewport();
+ this._resizeBar();
+ },
+
+ statics: {
+ _controlWidth: null,
+
+ /**
+ * Compute the width of the browser's scrollbar control, in pixels.
+ */
+ _getScrollbarControlWidth: function() {
+ var self = JX.Scrollbar;
+
+ if (self._controlWidth === null) {
+ var tmp = JX.$N('div', {className: 'jx-scrollbar-test'}, '-');
+ document.body.appendChild(tmp);
+ var d1 = JX.Vector.getDim(tmp);
+ tmp.style.overflowY = 'scroll';
+ var d2 = JX.Vector.getDim(tmp);
+ JX.DOM.remove(tmp);
+
+ self._controlWidth = (d2.x - d1.x);
+ }
+
+ return self._controlWidth;
+ }
+
+ },
+
+ members: {
+ _frame: null,
+ _viewport: null,
+ _content: null,
+
+ _bar: null,
+ _handle: null,
+
+ _timeout: null,
+ _dragOrigin: null,
+
+
+ /**
+ * After the user scrolls the page, show the scrollbar to give them
+ * feedback about their position.
+ */
+ _onscroll: function() {
+ this._showBar();
+ },
+
+
+ /**
+ * When the user mouses over the viewport, show the scrollbar.
+ */
+ _onenter: function() {
+ this._showBar();
+ },
+
+
+ /**
+ * When the user resizes the window, recalculate everything.
+ */
+ _onresize: function() {
+ this._resizeViewport();
+ this._resizeBar();
+ },
+
+
+ /**
+ * When the user clicks the bar area (but not the handle), jump up or
+ * down a page.
+ */
+ _onjump: function(e) {
+ if (e.getTarget() === this._handle) {
+ return;
+ }
+
+ var distance = JX.Vector.getDim(this._viewport).y * (7/8);
+ var epos = JX.$V(e);
+ var hpos = JX.$V(this._handle);
+
+ if (epos.y > hpos.y) {
+ this._viewport.scrollTop += distance;
+ } else {
+ this._viewport.scrollTop -= distance;
+ }
+ },
+
+
+ /**
+ * When the user clicks the scroll handle, begin dragging it.
+ */
+ _ondrag: function(e) {
+ e.kill();
+ this._dragOrigin = JX.$V(e).y;
+ },
+
+
+ /**
+ * As the user drags the scroll handle up or down, scroll the viewport.
+ */
+ _onmove: function(e) {
+ if (this._dragOrigin === null) {
+ return;
+ }
+
+ var offset = (JX.$V(e).y - this._dragOrigin);
+ var ratio = offset / JX.Vector.getDim(this._bar).y;
+ var target = ratio * JX.Vector.getDim(this._content).y;
+
+ this._viewport.scrollTop = target;
+ },
+
+
+ /**
+ * When the user releases the mouse after a drag, stop moving the
+ * viewport.
+ */
+ _ondrop: function() {
+ this._dragOrigin = null;
+ },
+
+
+ /**
+ * Shove the scrollbar on the viewport under the edge of the frame so the
+ * user can't see it.
+ */
+ _resizeViewport: function() {
+ var fdim = JX.Vector.getDim(this._frame);
+ fdim.x += JX.Scrollbar._getScrollbarControlWidth();
+ fdim.setDim(this._viewport);
+ },
+
+
+ /**
+ * Figure out the correct size and offset of the scrollbar handle.
+ */
+ _resizeBar: function() {
+ var cdim = JX.Vector.getDim(this._content);
+ var spos = JX.Vector.getAggregateScrollForNode(this._viewport);
+ var bdim = JX.Vector.getDim(this._bar);
+
+ var ratio = bdim.y / cdim.y;
+
+ var offset = Math.round(ratio * spos.y) + 2;
+ var size = Math.floor(ratio * (bdim.y - 2)) - 2;
+
+ if (size < cdim.y) {
+ this._handle.style.top = offset + 'px';
+ this._handle.style.height = size + 'px';
+
+ JX.DOM.show(this._handle);
+ } else {
+ JX.DOM.hide(this._handle);
+ }
+ },
+
+
+ /**
+ * Show the scrollbar for the next second.
+ */
+ _showBar: function() {
+ this._resizeBar();
+
+ JX.DOM.alterClass(this._handle, 'jx-scrollbar-visible', true);
+
+ this._clearTimeout();
+ this._timeout = setTimeout(JX.bind(this, this._hideBar), 1000);
+ },
+
+
+ /**
+ * Hide the scrollbar.
+ */
+ _hideBar: function() {
+ JX.DOM.alterClass(this._handle, 'jx-scrollbar-visible', false);
+ this._clearTimeout();
+ },
+
+
+ /**
+ * Clear the scrollbar hide timeout, if one is set.
+ */
+ _clearTimeout: function() {
+ if (this._timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = null;
+ }
+ }
+ }
+
+});
diff --git a/webroot/rsrc/js/application/slowvote/behavior-slowvote-embed.js b/webroot/rsrc/js/application/slowvote/behavior-slowvote-embed.js
--- a/webroot/rsrc/js/application/slowvote/behavior-slowvote-embed.js
+++ b/webroot/rsrc/js/application/slowvote/behavior-slowvote-embed.js
@@ -20,7 +20,7 @@
var request = new JX.Request(voteURI, function(r) {
var updated_poll = JX.$H(r.contentHTML);
- var root = JX.$('base-page');
+ var root = JX.$('phabricator-standard-page');
var polls = JX.DOM.scry(root, 'div', 'slowvote-embed');
diff --git a/webroot/rsrc/js/core/behavior-scrollbar.js b/webroot/rsrc/js/core/behavior-scrollbar.js
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/js/core/behavior-scrollbar.js
@@ -0,0 +1,9 @@
+/**
+ * @provides javelin-behavior-scrollbar
+ * @requires javelin-behavior
+ * javelin-scrollbar
+ */
+
+JX.behavior('scrollbar', function(config) {
+ new JX.Scrollbar(JX.$(config.nodeID));
+});
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 28, 5:11 PM (35 m, 49 s)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6940449
Default Alt Text
D11472.diff (20 KB)
Attached To
Mode
D11472: Replace the primary scrollbar with a fake one to prepare for a persistent chat column
Attached
Detach File
Event Timeline
Log In to Comment