-
- Powered by ReDoc
-
+
diff --git a/lib/components/Redoc/redoc.js b/lib/components/Redoc/redoc.js
index cf3b5207..3b59ad3b 100644
--- a/lib/components/Redoc/redoc.js
+++ b/lib/components/Redoc/redoc.js
@@ -2,22 +2,42 @@
import {RedocComponent, BaseComponent} from '../base';
import SchemaManager from '../../utils/SchemaManager';
+
import ApiInfo from '../ApiInfo/api-info';
import ApiLogo from '../ApiLogo/api-logo';
import MethodsList from '../MethodsList/methods-list';
import SideMenu from '../SideMenu/side-menu';
+import StickySidebar from '../../common/components/StickySidebar/sticky-sidebar';
+
import {ChangeDetectionStrategy} from 'angular2/core';
+import {ElementRef} from 'angular2/core';
+import {BrowserDomAdapter} from 'angular2/platform/browser';
+import detectScollParent from 'scrollparent';
+
@RedocComponent({
selector: 'redoc',
- providers: [SchemaManager],
+ providers: [SchemaManager, BrowserDomAdapter],
templateUrl: './lib/components/Redoc/redoc.html',
styleUrls: ['./lib/components/Redoc/redoc.css'],
- directives: [ApiInfo, ApiLogo, MethodsList, SideMenu],
+ directives: [ApiInfo, ApiLogo, MethodsList, SideMenu, StickySidebar],
changeDetection: ChangeDetectionStrategy.Default
})
export default class Redoc extends BaseComponent {
- constructor(schemaMgr) {
+ constructor(schemaMgr, elementRef) {
super(schemaMgr);
+ this.element = elementRef.nativeElement;
+
+ let DOM = new BrowserDomAdapter();
+ let el = this.element;
+ this.options = {};
+
+ //parse options (top level component doesn't support inputs)
+ this.options.scrollParent = detectScollParent(el);
+ this.options.scrollOffsetTop = parseInt(DOM.getAttribute(el, 'scroll-y-offset')) || 0;
}
}
+Redoc.parameters = Redoc.parameters.concat([[ElementRef]]);
+
+// this doesn't work in side-menu.js because of some circular references issue
+SideMenu.parameters = SideMenu.parameters.concat([[Redoc]]);
diff --git a/lib/components/Redoc/redoc.scss b/lib/components/Redoc/redoc.scss
index 8915f021..96a60806 100644
--- a/lib/components/Redoc/redoc.scss
+++ b/lib/components/Redoc/redoc.scss
@@ -1,10 +1,19 @@
@import '../../common/styles/variables';
+.redoc-wrap {
+ position: relative;
+}
+
side-menu {
display: block;
box-sizing: border-box;
}
+methods-list {
+ display: block;
+ overflow: hidden;
+}
+
api-info, .side-bar {
display: block;
padding: 10px 0;
@@ -19,21 +28,19 @@ api-logo {
text-align: center;
}
-.side-bar {
- position: fixed;
+sticky-sidebar {
width: $side-bar-width;
- height: 100%;
overflow-y: auto;
- overflow-x: hidden;;
+ overflow-x: hidden;
background-color: $side-bar-bg-color;
}
-.api-content {
+#api-content {
margin-left: $side-bar-width;
}
footer {
- text-align: center;
+ text-align: right;
padding: 10px;
font-size: 15px;
diff --git a/lib/components/Redoc/redoc.spec.js b/lib/components/Redoc/redoc.spec.js
index 87d037d2..dc03c488 100644
--- a/lib/components/Redoc/redoc.spec.js
+++ b/lib/components/Redoc/redoc.spec.js
@@ -2,6 +2,7 @@
import { getChildDebugElement } from 'tests/helpers';
import {Component, View, provide} from 'angular2/core';
+import {BrowserDomAdapter} from 'angular2/platform/browser';
import {
TestComponentBuilder,
@@ -18,7 +19,8 @@ describe('Redoc components', () => {
describe('Redoc Component', () => {
let builder;
beforeEachProviders(() => [
- provide(SchemaManager, {useValue: new SchemaManager()})
+ provide(SchemaManager, {useValue: new SchemaManager()}),
+ provide(BrowserDomAdapter, {useValue: new BrowserDomAdapter()})
]);
beforeEach(injectAsync([TestComponentBuilder, SchemaManager], (tcb, schemaMgr) => {
builder = tcb;
@@ -42,6 +44,17 @@ describe('Redoc components', () => {
done();
}, err => done.fail(err));
});
+
+ it('should parse component options from host element', (done) => {
+ builder.createAsync(TestApp).then(fixture => {
+ let component = getChildDebugElement(fixture.debugElement, 'redoc').componentInstance;
+ fixture.detectChanges();
+ console.log(component.options.scrollOffsetTop);
+ component.options.scrollOffsetTop.should.be.equal(50);
+ fixture.destroy();
+ done();
+ }, err => done.fail(err));
+ });
});
});
@@ -50,7 +63,7 @@ describe('Redoc components', () => {
@View({
directives: [Redoc],
template:
- `
`
+ `
`
})
class TestApp {
}
diff --git a/lib/components/SideMenu/side-menu.js b/lib/components/SideMenu/side-menu.js
index 2cd551bc..59180fad 100644
--- a/lib/components/SideMenu/side-menu.js
+++ b/lib/components/SideMenu/side-menu.js
@@ -1,11 +1,10 @@
'use strict';
import {RedocComponent, BaseComponent} from '../base';
-import {NgZone, ChangeDetectionStrategy} from 'angular2/core';
import {redocEvents} from '../../events';
-import detectScollParent from 'scrollparent';
-import {document} from 'angular2/src/facade/browser';
+import {NgZone, ChangeDetectionStrategy} from 'angular2/core';
+import {document} from 'angular2/src/facade/browser';
import {BrowserDomAdapter} from 'angular2/platform/browser';
import {global} from 'angular2/src/facade/lang';
@@ -23,18 +22,18 @@ const INVIEW_POSITION = {
@RedocComponent({
selector: 'side-menu',
- providers: [BrowserDomAdapter],
templateUrl: './lib/components/SideMenu/side-menu.html',
styleUrls: ['./lib/components/SideMenu/side-menu.css'],
changeDetection: ChangeDetectionStrategy.Default
})
export default class SideMenu extends BaseComponent {
- constructor(schemaMgr, adapter, zone) {
+ constructor(schemaMgr, adapter, zone, redoc) {
super(schemaMgr);
this.zone = zone;
this.adapter = adapter;
+ this.redoc = redoc;
- this.scrollParent = detectScollParent(document.querySelector('methods-list'));
+ this.scrollParent = this.redoc.options.scrollParent;
// for some reason constructor is not run inside zone
// as workaround running it manually
@@ -66,7 +65,7 @@ export default class SideMenu extends BaseComponent {
bindEvents() {
this.prevOffsetY = this.scrollY();
- this.viewBoxTop = this.scrollParent.offsetTop || 0;
+ this.scrollOffsetY = this.redoc.options.scrollOffsetTop || 0;
this._cancel = {};
this._cancel.scroll = this.adapter.onAndCancel(this.scrollParent, 'scroll', () => { this.scrollHandler(); });
this._cancel.hash = this.adapter.onAndCancel(global, 'hashchange', evt => this.hashScroll(evt));
@@ -85,7 +84,7 @@ export default class SideMenu extends BaseComponent {
scrollTo(el) {
// TODO: rewrite this to use offsetTop as more reliable solution
let subjRect = el.getBoundingClientRect();
- let offset = this.scrollY() + subjRect.top - this.viewBoxTop + 1;
+ let offset = this.scrollY() + subjRect.top - this.scrollOffsetY + 1;
if (this.scrollParent.scrollTo) {
this.scrollParent.scrollTo(0, offset);
} else {
@@ -163,11 +162,11 @@ export default class SideMenu extends BaseComponent {
/* returns 1 if element if above the view, 0 if in view and -1 below the view */
getElementInViewPos(el) {
- if (Math.floor(el.getBoundingClientRect().top) > this.viewBoxTop) {
+ if (Math.floor(el.getBoundingClientRect().top) > this.scrollOffsetY) {
return INVIEW_POSITION.ABOVE;
}
- if (el.getBoundingClientRect().bottom <= this.viewBoxTop) {
+ if (el.getBoundingClientRect().bottom <= this.scrollOffsetY) {
return INVIEW_POSITION.BELLOW;
}
return INVIEW_POSITION.INVIEW;
diff --git a/lib/components/SideMenu/side-menu.spec.js b/lib/components/SideMenu/side-menu.spec.js
index 936bcb47..0d29f025 100644
--- a/lib/components/SideMenu/side-menu.spec.js
+++ b/lib/components/SideMenu/side-menu.spec.js
@@ -2,6 +2,7 @@
import { getChildDebugElement, mouseclick} from 'tests/helpers';
import {Component, View, provide, ViewMetadata} from 'angular2/core';
+import {BrowserDomAdapter} from 'angular2/platform/browser';
import {
TestComponentBuilder,
@@ -14,15 +15,24 @@ import {
import {redocEvents} from 'lib/events';
import MethodsList from 'lib/components/MethodsList/methods-list';
import SideMenu from 'lib/components/SideMenu/side-menu';
+import Redoc from 'lib/components/Redoc/redoc';
import SchemaManager from 'lib/utils/SchemaManager';
+let _mockRedoc = {
+ options: {
+ scrollOffsetTop: 0,
+ scrollParent: window
+ }
+};
describe('Redoc components', () => {
describe('SideMenu Component', () => {
let builder;
let component;
let fixture;
beforeEachProviders(() => [
- provide(SchemaManager, {useValue: new SchemaManager()})
+ provide(SchemaManager, {useValue: new SchemaManager()}),
+ provide(BrowserDomAdapter, {useValue: new BrowserDomAdapter()}),
+ provide(Redoc, {useValue: _mockRedoc})
]);
beforeEach(injectAsync([TestComponentBuilder, SchemaManager], (tcb, schemaMgr) => {
builder = tcb;
@@ -50,10 +60,6 @@ describe('Redoc components', () => {
expect(component.data).not.toBeNull();
});
- it('should use window as scrollParent', () => {
- expect(component.scrollParent).toBe(window);
- });
-
it('should run hashScroll when redoc bootstrapped', (done) => {
spyOn(component.adapter, 'getLocation').and.returnValue({hash: ''});
spyOn(component, 'hashScroll').and.stub();
@@ -99,6 +105,7 @@ describe('Redoc components', () => {
fixture = _fixture;
component = getChildDebugElement(fixture.debugElement, 'side-menu').componentInstance;
menuNativeEl = getChildDebugElement(fixture.debugElement, 'side-menu').nativeElement;
+ component.scrollParent = _fixture.nativeElement.children[0];
fixture.detectChanges();
done();
@@ -114,10 +121,6 @@ describe('Redoc components', () => {
expect(component.data).not.toBeNull();
});
- it('should use scrollable div as scrollParent', () => {
- component.scrollParent.should.be.instanceof(Element);
- });
-
it('should scroll to method when location hash is present', (done) => {
let hash = '#pet/paths/~1pet~1findByStatus/get';
spyOn(component.adapter, 'getLocation').and.returnValue({hash: hash});