mirror of
				https://github.com/Redocly/redoc.git
				synced 2025-10-31 07:47:29 +03:00 
			
		
		
		
	make scrollYOffset option consume selector and function
This commit is contained in:
		
							parent
							
								
									db8f9e8a96
								
							
						
					
					
						commit
						1c4a3ca20f
					
				|  | @ -12,7 +12,7 @@ | |||
|     </nav> | ||||
|     </nav> | ||||
| 
 | ||||
|     <redoc scroll-y-offset="50"> | ||||
|     <redoc scroll-y-offset="body > nav"> | ||||
|       Loading... | ||||
|     </redoc> | ||||
| 
 | ||||
|  |  | |||
|  | @ -37,7 +37,7 @@ export default class StickySidebar { | |||
|   } | ||||
| 
 | ||||
|   updatePosition() { | ||||
|     if ( this.scrollY + this.scrollYOffset >= this.redocEl.offsetTop) { | ||||
|     if ( this.scrollY + this.scrollYOffset() >= this.redocEl.offsetTop) { | ||||
|       this.stick(); | ||||
|     } else { | ||||
|       this.unstick(); | ||||
|  | @ -46,7 +46,7 @@ export default class StickySidebar { | |||
| 
 | ||||
|   stick() { | ||||
|     this.adapter.setStyle(this.element, 'position', 'fixed'); | ||||
|     this.adapter.setStyle(this.element, 'top', this.scrollYOffset); | ||||
|     this.adapter.setStyle(this.element, 'top', this.scrollYOffset()); | ||||
|   } | ||||
| 
 | ||||
|   unstick() { | ||||
|  | @ -60,7 +60,6 @@ export default class StickySidebar { | |||
| 
 | ||||
|   ngOnInit() { | ||||
|     this.redocEl = this.element.offsetParent; | ||||
|     this.scrollYOffset = parseInt(this.scrollYOffset); | ||||
|     this.bind(); | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
|  | @ -75,6 +75,6 @@ class TestApp { | |||
|   constructor() { | ||||
|     this.options = {}; | ||||
|     this.scrollParent = window; | ||||
|     this.options.scrollYOffset = 20; | ||||
|     this.options.scrollYOffset = () => 20; | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -8,13 +8,15 @@ 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 {options as defaultOptions} from '../../index'; | ||||
| import {options as defaultOptions} from '../../options'; | ||||
| 
 | ||||
| import {ChangeDetectionStrategy} from 'angular2/core'; | ||||
| import {ElementRef} from 'angular2/core'; | ||||
| import {BrowserDomAdapter} from 'angular2/platform/browser'; | ||||
| import detectScollParent from 'scrollparent'; | ||||
| 
 | ||||
| import {isFunction} from 'angular2/src/facade/lang'; | ||||
| 
 | ||||
| let optionNames = new Set(['scrollYOffset']); | ||||
| 
 | ||||
| @RedocComponent({ | ||||
|  | @ -37,6 +39,7 @@ export default class Redoc extends BaseComponent { | |||
|     this.scrollParent = detectScollParent(el); | ||||
|     this.parseOptions(); | ||||
|     this.options = Object.assign({}, defaultOptions, this.options); | ||||
|     this.normalizeOptions(); | ||||
|   } | ||||
| 
 | ||||
|   parseOptions() { | ||||
|  | @ -53,9 +56,28 @@ export default class Redoc extends BaseComponent { | |||
|       .forEach(option => { | ||||
|         this.options[option.name] = attributesMap.get(option.attrName); | ||||
|       }); | ||||
|   } | ||||
| 
 | ||||
|     // post-process options
 | ||||
|     this.options.scrollYOffset = parseInt(this.options.scrollYOffset); | ||||
|   normalizeOptions() { | ||||
|     // modify scrollYOffset to always be a function
 | ||||
|     if (!isFunction(this.options.scrollYOffset)) { | ||||
|       if (isFinite(this.options.scrollYOffset)) { | ||||
|         // if number specified create function that returns this value
 | ||||
|         let numberOffset = parseFloat(this.options.scrollYOffset); | ||||
|         this.options.scrollYOffset = () => numberOffset; | ||||
|       } else { | ||||
|         // if selector or node function that returns bottom offset of this node
 | ||||
|         let el = this.options.scrollYOffset; | ||||
|         if (!(el instanceof Node)) { | ||||
|           el = this.dom.query(el); | ||||
|         } | ||||
|         if (!el) { | ||||
|           this.options.scrollYOffset = () => 0; | ||||
|         } else { | ||||
|           this.options.scrollYOffset = () => el.offsetTop + el.offsetHeight; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| Redoc.parameters = Redoc.parameters.concat([[ElementRef], [BrowserDomAdapter]]); | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| 'use strict'; | ||||
| 
 | ||||
| import { getChildDebugElement } from 'tests/helpers'; | ||||
| import {Component, View, provide} from 'angular2/core'; | ||||
| import {Component, View, ViewMetadata, provide} from 'angular2/core'; | ||||
| import {BrowserDomAdapter} from 'angular2/platform/browser'; | ||||
| 
 | ||||
| import { | ||||
|  | @ -14,6 +14,7 @@ import { | |||
| 
 | ||||
| import Redoc from 'lib/components/Redoc/redoc'; | ||||
| import SchemaManager from 'lib/utils/SchemaManager'; | ||||
| import {options} from 'lib/options'; | ||||
| 
 | ||||
| describe('Redoc components', () => { | ||||
|   describe('Redoc Component', () => { | ||||
|  | @ -45,14 +46,60 @@ describe('Redoc components', () => { | |||
|       }, 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; | ||||
|     describe('Options', () => { | ||||
|       let component; | ||||
|       let fixture; | ||||
| 
 | ||||
|       function build(tmpl, cb) { | ||||
|         builder = builder.overrideView(TestApp, | ||||
|           new ViewMetadata({template: tmpl, directives: [Redoc]})); | ||||
|         builder.createAsync(TestApp).then(_fixture => { | ||||
|           fixture = _fixture; | ||||
|           component = getChildDebugElement(fixture.debugElement, 'redoc').componentInstance; | ||||
|           fixture.detectChanges(); | ||||
|         component.options.scrollYOffset.should.be.equal(50); | ||||
|           cb(); | ||||
|         }, err => cb(err)); | ||||
|       } | ||||
| 
 | ||||
|       afterEach(() => { | ||||
|         fixture.destroy(); | ||||
|       }); | ||||
| 
 | ||||
|       it('should parse numeric scrollYOffset', (done) => { | ||||
|         build(`<redoc scroll-y-offset="50"></redoc>`, err => { | ||||
|           if (err) return done.fail(err); | ||||
|           component.options.scrollYOffset().should.be.equal(50); | ||||
|           done(); | ||||
|       }, err => done.fail(err)); | ||||
|         }); | ||||
|       }); | ||||
| 
 | ||||
|       it('should parse selector scrollYOffset', (done) => { | ||||
|         build(`<div id="test" style="position: fixed; height: 50px; top:0"> </div>
 | ||||
|               <redoc scroll-y-offset="#test"></redoc>`, err => { | ||||
|           if (err) return done.fail(err); | ||||
|           component.options.scrollYOffset().should.be.equal(50); | ||||
|           done(); | ||||
|         }); | ||||
|       }); | ||||
| 
 | ||||
|       it('should return 0 for incorrect selector scrollYOffset', (done) => { | ||||
|         build(`<div id="test" style="position: fixed; height: 50px; top:0"> </div>
 | ||||
|               <redoc scroll-y-offset="#test2"></redoc>`, err => { | ||||
|           if (err) return done.fail(err); | ||||
|           component.options.scrollYOffset().should.be.equal(0); | ||||
|           done(); | ||||
|         }); | ||||
|       }); | ||||
| 
 | ||||
|       it('should handle function scrollYOffset', (done) => { | ||||
|         options.scrollYOffset = () => 123; | ||||
|         build(`<redoc></redoc>`, err => { | ||||
|           if (err) return done.fail(err); | ||||
|           component.options.scrollYOffset().should.be.equal(123); | ||||
|           options.scrollYOffset = 0; | ||||
|           done(); | ||||
|         }); | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
|  | @ -62,7 +109,7 @@ describe('Redoc components', () => { | |||
| @View({ | ||||
|   directives: [Redoc], | ||||
|   template: | ||||
|       `<redoc scroll-y-offset="50"></redoc>` | ||||
|       `<redoc></redoc>` | ||||
| }) | ||||
| class TestApp { | ||||
| } | ||||
|  |  | |||
|  | @ -84,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.scrollYOffset + 1; | ||||
|     let offset = this.scrollY() + subjRect.top - this.scrollYOffset() + 1; | ||||
|     if (this.scrollParent.scrollTo) { | ||||
|       this.scrollParent.scrollTo(0, offset); | ||||
|     } else { | ||||
|  | @ -162,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.scrollYOffset) { | ||||
|     if (Math.floor(el.getBoundingClientRect().top) > this.scrollYOffset()) { | ||||
|       return INVIEW_POSITION.ABOVE; | ||||
|     } | ||||
| 
 | ||||
|     if (el.getBoundingClientRect().bottom <= this.scrollYOffset) { | ||||
|     if (el.getBoundingClientRect().bottom <= this.scrollYOffset()) { | ||||
|       return INVIEW_POSITION.BELLOW; | ||||
|     } | ||||
|     return INVIEW_POSITION.INVIEW; | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ import SchemaManager from 'lib/utils/SchemaManager'; | |||
| 
 | ||||
| let _mockRedoc = { | ||||
|   options: { | ||||
|     scrollYOffset: 0 | ||||
|     scrollYOffset: () => 0 | ||||
|   }, | ||||
|   scrollParent: window | ||||
| }; | ||||
|  |  | |||
|  | @ -6,10 +6,6 @@ import SchemaManager from './utils/SchemaManager'; | |||
| import {redocEvents} from './events'; | ||||
| export * from  './components/index'; | ||||
| 
 | ||||
| export var options = { | ||||
|   scrollYOffset: 0 | ||||
| }; | ||||
| 
 | ||||
| export function init(schemaUrl) { | ||||
|   var promise = new Promise(function(resolve, reject) { | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										5
									
								
								lib/options.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								lib/options.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| 'use strict'; | ||||
| 
 | ||||
| export var options = { | ||||
|   scrollYOffset: 0 | ||||
| }; | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user