Best JavaScript code snippet using wpt
balloonpanelview.js
Source:balloonpanelview.js
1/**2 * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.3 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license4 */5/* global window, document, Event */6import ViewCollection from '../../../src/viewcollection';7import BalloonPanelView, { generatePositions } from '../../../src/panel/balloon/balloonpanelview';8import ButtonView from '../../../src/button/buttonview';9import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';10import { Rect } from '@ckeditor/ckeditor5-utils';11describe( 'BalloonPanelView', () => {12 let view;13 testUtils.createSinonSandbox();14 beforeEach( () => {15 view = new BalloonPanelView();16 view.render();17 document.body.appendChild( view.element );18 } );19 afterEach( () => {20 if ( view ) {21 view.element.remove();22 view.destroy();23 }24 } );25 describe( 'constructor()', () => {26 it( 'should create element from template', () => {27 expect( view.element.tagName ).to.equal( 'DIV' );28 expect( view.element.classList.contains( 'ck' ) ).to.true;29 expect( view.element.classList.contains( 'ck-balloon-panel' ) ).to.true;30 } );31 it( 'should set default values', () => {32 expect( view.top ).to.equal( 0 );33 expect( view.left ).to.equal( 0 );34 expect( view.position ).to.equal( 'arrow_nw' );35 expect( view.isVisible ).to.equal( false );36 expect( view.withArrow ).to.equal( true );37 } );38 it( 'creates view#content collection', () => {39 expect( view.content ).to.be.instanceOf( ViewCollection );40 } );41 } );42 describe( 'DOM bindings', () => {43 describe( 'arrow', () => {44 it( 'should react on view#position', () => {45 expect( view.element.classList.contains( 'ck-balloon-panel_arrow_nw' ) ).to.true;46 view.position = 'arrow_ne';47 expect( view.element.classList.contains( 'ck-balloon-panel_arrow_ne' ) ).to.true;48 } );49 it( 'should react on view#withArrow', () => {50 expect( view.element.classList.contains( 'ck-balloon-panel_with-arrow' ) ).to.be.true;51 view.withArrow = false;52 expect( view.element.classList.contains( 'ck-balloon-panel_with-arrow' ) ).to.be.false;53 } );54 } );55 describe( 'isVisible', () => {56 it( 'should react on view#isvisible', () => {57 expect( view.element.classList.contains( 'ck-balloon-panel_visible' ) ).to.false;58 view.isVisible = true;59 expect( view.element.classList.contains( 'ck-balloon-panel_visible' ) ).to.true;60 } );61 } );62 describe( 'styles', () => {63 it( 'should react on view#top', () => {64 expect( view.element.style.top ).to.equal( '0px' );65 view.top = 10;66 expect( view.element.style.top ).to.equal( '10px' );67 } );68 it( 'should react on view#left', () => {69 expect( view.element.style.left ).to.equal( '0px' );70 view.left = 10;71 expect( view.element.style.left ).to.equal( '10px' );72 } );73 } );74 describe( 'class', () => {75 it( 'should set additional class to the view#element', () => {76 view.class = 'foo';77 expect( view.element.classList.contains( 'foo' ) ).to.true;78 view.class = '';79 expect( view.element.classList.contains( 'foo' ) ).to.false;80 } );81 } );82 describe( 'children', () => {83 it( 'should react on view#content', () => {84 expect( view.element.childNodes.length ).to.equal( 0 );85 const button = new ButtonView( { t() {} } );86 view.content.add( button );87 expect( view.element.childNodes.length ).to.equal( 1 );88 } );89 } );90 } );91 describe( 'show()', () => {92 it( 'should set view#isVisible as true', () => {93 view.isVisible = false;94 view.show();95 expect( view.isVisible ).to.true;96 } );97 } );98 describe( 'hide()', () => {99 it( 'should set view#isVisible as false', () => {100 view.isVisible = true;101 view.hide();102 expect( view.isVisible ).to.false;103 } );104 } );105 describe( 'attachTo()', () => {106 let target, limiter;107 beforeEach( () => {108 limiter = document.createElement( 'div' );109 target = document.createElement( 'div' );110 document.body.appendChild( limiter );111 document.body.appendChild( target );112 // Mock balloon panel element dimensions.113 mockBoundingBox( view.element, {114 top: 0,115 left: 0,116 width: 100,117 height: 100118 } );119 // Mock window dimensions.120 testUtils.sinon.stub( window, 'innerWidth' ).value( 500 );121 testUtils.sinon.stub( window, 'innerHeight' ).value( 500 );122 testUtils.sinon.stub( window, 'scrollX' ).value( 0 );123 testUtils.sinon.stub( window, 'scrollY' ).value( 0 );124 } );125 afterEach( () => {126 limiter.remove();127 target.remove();128 } );129 it( 'should use default options', () => {130 const spy = testUtils.sinon.spy( BalloonPanelView, '_getOptimalPosition' );131 view.attachTo( { target } );132 sinon.assert.calledWithExactly( spy, sinon.match( {133 element: view.element,134 target,135 positions: [136 BalloonPanelView.defaultPositions.southArrowNorth,137 BalloonPanelView.defaultPositions.southArrowNorthMiddleWest,138 BalloonPanelView.defaultPositions.southArrowNorthMiddleEast,139 BalloonPanelView.defaultPositions.southArrowNorthWest,140 BalloonPanelView.defaultPositions.southArrowNorthEast,141 BalloonPanelView.defaultPositions.northArrowSouth,142 BalloonPanelView.defaultPositions.northArrowSouthMiddleWest,143 BalloonPanelView.defaultPositions.northArrowSouthMiddleEast,144 BalloonPanelView.defaultPositions.northArrowSouthWest,145 BalloonPanelView.defaultPositions.northArrowSouthEast,146 BalloonPanelView.defaultPositions.viewportStickyNorth147 ],148 limiter: document.body,149 fitInViewport: true150 } ) );151 } );152 it( 'should parse optimal position offset to int', () => {153 testUtils.sinon.stub( BalloonPanelView, '_getOptimalPosition' ).returns( {154 top: 10.345,155 left: 10.345,156 name: 'position'157 } );158 view.attachTo( { target, limiter } );159 expect( view.top ).to.equal( 10 );160 expect( view.left ).to.equal( 10 );161 } );162 it( 'should set and override withArrow property', () => {163 testUtils.sinon.stub( BalloonPanelView, '_getOptimalPosition' ).returns( {164 top: 10.345,165 left: 10.345,166 name: 'position'167 } );168 view.withArrow = false;169 view.attachTo( { target, limiter } );170 expect( view.withArrow ).to.be.true;171 view.set( 'withArrow', false );172 view.attachTo( { target, limiter } );173 expect( view.withArrow ).to.be.true;174 BalloonPanelView._getOptimalPosition.restore();175 testUtils.sinon.stub( BalloonPanelView, '_getOptimalPosition' ).returns( {176 top: 10.345,177 left: 10.345,178 name: 'position',179 config: {180 withArrow: false181 }182 } );183 view.attachTo( { target, limiter } );184 expect( view.withArrow ).to.be.false;185 } );186 describe( 'limited by limiter element', () => {187 beforeEach( () => {188 // Mock limiter element dimensions.189 mockBoundingBox( limiter, {190 left: 0,191 top: 0,192 width: 500,193 height: 500194 } );195 } );196 it( 'should put balloon on the `south east` side of the target element at default', () => {197 // Place target element at the center of the limiter.198 mockBoundingBox( target, {199 top: 225,200 left: 225,201 width: 50,202 height: 50203 } );204 view.attachTo( { target, limiter } );205 expect( view.position ).to.equal( 'arrow_n' );206 } );207 it( 'should put balloon on the `south east` side of the target element when ' +208 'target is on the top left side of the limiter', () => {209 mockBoundingBox( target, {210 top: 0,211 left: 0,212 width: 50,213 height: 50214 } );215 view.attachTo( { target, limiter } );216 expect( view.position ).to.equal( 'arrow_nw' );217 } );218 it( 'should put balloon on the `south west` side of the target element when target is on the right side of the limiter', () => {219 mockBoundingBox( target, {220 top: 0,221 left: 450,222 width: 50,223 height: 50224 } );225 view.attachTo( { target, limiter } );226 expect( view.position ).to.equal( 'arrow_ne' );227 } );228 it( 'should put balloon on the `north east` side of the target element when target is on the bottom of the limiter ', () => {229 mockBoundingBox( target, {230 top: 450,231 left: 0,232 width: 50,233 height: 50234 } );235 view.attachTo( { target, limiter } );236 expect( view.position ).to.equal( 'arrow_sw' );237 } );238 it( 'should put balloon on the `north west` side of the target element when ' +239 'target is on the bottom right of the limiter', () => {240 mockBoundingBox( target, {241 top: 450,242 left: 450,243 width: 50,244 height: 50245 } );246 view.attachTo( { target, limiter } );247 expect( view.position ).to.equal( 'arrow_se' );248 } );249 // https://github.com/ckeditor/ckeditor5-ui-default/issues/126250 it( 'works in a positioned ancestor (position: absolute)', () => {251 const positionedAncestor = document.createElement( 'div' );252 positionedAncestor.style.position = 'absolute';253 positionedAncestor.style.top = '100px';254 positionedAncestor.style.left = '100px';255 positionedAncestor.appendChild( view.element );256 document.body.appendChild( positionedAncestor );257 positionedAncestor.appendChild( view.element );258 mockBoundingBox( positionedAncestor, {259 top: 100,260 left: 100,261 width: 10,262 height: 10263 } );264 mockBoundingBox( target, {265 top: 0,266 left: 0,267 width: 100,268 height: 100269 } );270 view.attachTo( { target, limiter } );271 expect( view.top ).to.equal( BalloonPanelView.arrowVerticalOffset );272 expect( view.left ).to.equal( -100 );273 positionedAncestor.remove();274 } );275 // https://github.com/ckeditor/ckeditor5-ui-default/issues/126276 it( 'works in a positioned ancestor (position: static)', () => {277 const positionedAncestor = document.createElement( 'div' );278 positionedAncestor.style.position = 'static';279 positionedAncestor.appendChild( view.element );280 document.body.appendChild( positionedAncestor );281 positionedAncestor.appendChild( view.element );282 mockBoundingBox( target, {283 top: 0,284 left: 0,285 width: 100,286 height: 100287 } );288 view.attachTo( { target, limiter } );289 expect( view.top ).to.equal( BalloonPanelView.arrowVerticalOffset + 100 );290 expect( view.left ).to.equal( 0 );291 positionedAncestor.remove();292 } );293 } );294 describe( 'limited by viewport', () => {295 it( 'should put balloon on the `south west` position when `south east` is limited', () => {296 mockBoundingBox( limiter, {297 left: 0,298 top: 0,299 width: 500,300 height: 500301 } );302 mockBoundingBox( target, {303 top: 0,304 left: 225,305 width: 50,306 height: 50307 } );308 // Note: No sandboxing here. Otherwise, it would restore to the previously stubbed value.309 sinon.stub( window, 'innerWidth' ).value( 275 );310 view.attachTo( { target, limiter } );311 expect( view.position ).to.equal( 'arrow_ne' );312 } );313 it( 'should put balloon on the `south east` position when `south west` is limited', () => {314 mockBoundingBox( limiter, {315 top: 0,316 left: -400,317 width: 500,318 height: 500319 } );320 mockBoundingBox( target, {321 top: 0,322 left: 0,323 width: 50,324 height: 50325 } );326 view.attachTo( { target, limiter } );327 expect( view.position ).to.equal( 'arrow_nw' );328 } );329 it( 'should put balloon on the `north east` position when `south east` is limited', () => {330 mockBoundingBox( limiter, {331 left: 0,332 top: 0,333 width: 500,334 height: 500335 } );336 mockBoundingBox( target, {337 top: 225,338 left: 0,339 width: 50,340 height: 50341 } );342 // Note: No sandboxing here. Otherwise, it would restore to the previously stubbed value.343 sinon.stub( window, 'innerHeight' ).value( 275 );344 view.attachTo( { target, limiter } );345 expect( view.position ).to.equal( 'arrow_sw' );346 } );347 it( 'should put balloon on the `south east` position when `north east` is limited', () => {348 mockBoundingBox( limiter, {349 left: 0,350 top: -400,351 width: 500,352 height: 500353 } );354 mockBoundingBox( target, {355 top: 0,356 left: 0,357 width: 50,358 height: 50359 } );360 view.attachTo( { target, limiter } );361 expect( view.position ).to.equal( 'arrow_nw' );362 } );363 } );364 } );365 describe( 'pin() and unpin()', () => {366 let attachToSpy, target, targetParent, limiter, notRelatedElement;367 beforeEach( () => {368 attachToSpy = sinon.spy( view, 'attachTo' );369 limiter = document.createElement( 'div' );370 targetParent = document.createElement( 'div' );371 target = document.createElement( 'div' );372 notRelatedElement = document.createElement( 'div' );373 view.show();374 targetParent.appendChild( target );375 document.body.appendChild( targetParent );376 document.body.appendChild( limiter );377 document.body.appendChild( notRelatedElement );378 } );379 afterEach( () => {380 targetParent.remove();381 limiter.remove();382 notRelatedElement.remove();383 } );384 describe( 'pin()', () => {385 it( 'should show the balloon', () => {386 const spy = sinon.spy( view, 'show' );387 view.hide();388 view.pin( { target, limiter } );389 sinon.assert.calledOnce( spy );390 } );391 it( 'should start pinning when the balloon is visible', () => {392 view.pin( { target, limiter } );393 sinon.assert.calledOnce( attachToSpy );394 view.hide();395 targetParent.dispatchEvent( new Event( 'scroll' ) );396 view.show();397 sinon.assert.calledTwice( attachToSpy );398 targetParent.dispatchEvent( new Event( 'scroll' ) );399 sinon.assert.calledThrice( attachToSpy );400 } );401 it( 'should stop pinning when the balloon becomes invisible', () => {402 view.show();403 view.pin( { target, limiter } );404 sinon.assert.calledOnce( attachToSpy );405 view.hide();406 targetParent.dispatchEvent( new Event( 'scroll' ) );407 sinon.assert.calledOnce( attachToSpy );408 } );409 it( 'should unpin if already pinned', () => {410 const unpinSpy = testUtils.sinon.spy( view, 'unpin' );411 view.show();412 sinon.assert.notCalled( attachToSpy );413 view.pin( { target, limiter } );414 sinon.assert.calledOnce( attachToSpy );415 view.pin( { target, limiter } );416 sinon.assert.calledTwice( unpinSpy );417 targetParent.dispatchEvent( new Event( 'scroll' ) );418 sinon.assert.calledThrice( attachToSpy );419 } );420 it( 'should keep the balloon pinned to the target when any of the related elements is scrolled', () => {421 view.pin( { target, limiter } );422 sinon.assert.calledOnce( attachToSpy );423 sinon.assert.calledWith( attachToSpy.lastCall, { target, limiter } );424 targetParent.dispatchEvent( new Event( 'scroll' ) );425 sinon.assert.calledTwice( attachToSpy );426 sinon.assert.calledWith( attachToSpy.lastCall, { target, limiter } );427 limiter.dispatchEvent( new Event( 'scroll' ) );428 sinon.assert.calledThrice( attachToSpy );429 sinon.assert.calledWith( attachToSpy.lastCall, { target, limiter } );430 notRelatedElement.dispatchEvent( new Event( 'scroll' ) );431 // Nothing's changed.432 sinon.assert.calledThrice( attachToSpy );433 sinon.assert.calledWith( attachToSpy.lastCall, { target, limiter } );434 } );435 it( 'should keep the balloon pinned to the target when the browser window is being resized', () => {436 view.pin( { target, limiter } );437 sinon.assert.calledOnce( attachToSpy );438 sinon.assert.calledWith( attachToSpy.lastCall, { target, limiter } );439 window.dispatchEvent( new Event( 'resize' ) );440 sinon.assert.calledTwice( attachToSpy );441 sinon.assert.calledWith( attachToSpy.lastCall, { target, limiter } );442 } );443 it( 'should stop attaching when the balloon is hidden', () => {444 view.pin( { target, limiter } );445 sinon.assert.calledOnce( attachToSpy );446 view.hide();447 window.dispatchEvent( new Event( 'resize' ) );448 window.dispatchEvent( new Event( 'scroll' ) );449 // Still once.450 sinon.assert.calledOnce( attachToSpy );451 } );452 it( 'should stop attaching once the view is destroyed', () => {453 view.pin( { target, limiter } );454 sinon.assert.calledOnce( attachToSpy );455 view.destroy();456 view.element.remove();457 view = null;458 window.dispatchEvent( new Event( 'resize' ) );459 window.dispatchEvent( new Event( 'scroll' ) );460 // Still once.461 sinon.assert.calledOnce( attachToSpy );462 } );463 it( 'should set document.body as the default limiter', () => {464 view.pin( { target } );465 sinon.assert.calledOnce( attachToSpy );466 document.body.dispatchEvent( new Event( 'scroll' ) );467 sinon.assert.calledTwice( attachToSpy );468 } );469 it( 'should work for Range as a target', () => {470 const element = document.createElement( 'div' );471 const range = document.createRange();472 element.appendChild( document.createTextNode( 'foo bar' ) );473 document.body.appendChild( element );474 range.selectNodeContents( element );475 view.pin( { target: range } );476 sinon.assert.calledOnce( attachToSpy );477 element.dispatchEvent( new Event( 'scroll' ) );478 sinon.assert.calledTwice( attachToSpy );479 element.remove();480 } );481 it( 'should work for a Rect as a target', () => {482 // Just check if this normally works without errors.483 const rect = {};484 view.pin( { target: rect, limiter } );485 sinon.assert.calledOnce( attachToSpy );486 limiter.dispatchEvent( new Event( 'scroll' ) );487 sinon.assert.calledTwice( attachToSpy );488 } );489 it( 'should work for a function as a target/limiter', () => {490 // Just check if this normally works without errors.491 const rect = {};492 view.pin( {493 target() { return rect; },494 limiter() { return limiter; }495 } );496 sinon.assert.calledOnce( attachToSpy );497 limiter.dispatchEvent( new Event( 'scroll' ) );498 sinon.assert.calledTwice( attachToSpy );499 } );500 // https://github.com/ckeditor/ckeditor5-ui/issues/227501 it( 'should react to #scroll from anywhere when the target is not an HTMLElement or Range', () => {502 const rect = {};503 view.pin( { target: rect } );504 sinon.assert.calledOnce( attachToSpy );505 notRelatedElement.dispatchEvent( new Event( 'scroll' ) );506 sinon.assert.calledTwice( attachToSpy );507 } );508 // https://github.com/ckeditor/ckeditor5-ui/issues/260509 it( 'should react to #scroll from anywhere when the limiter is not an HTMLElement` or Range', () => {510 const rect = {};511 view.pin( { target, limiter: rect } );512 sinon.assert.calledOnce( attachToSpy );513 notRelatedElement.dispatchEvent( new Event( 'scroll' ) );514 sinon.assert.calledTwice( attachToSpy );515 } );516 } );517 describe( 'unpin()', () => {518 it( 'should hide the balloon if pinned', () => {519 const spy = sinon.spy( view, 'hide' );520 view.pin( { target, limiter } );521 view.unpin();522 sinon.assert.calledOnce( spy );523 } );524 it( 'should stop attaching', () => {525 view.pin( { target, limiter } );526 sinon.assert.calledOnce( attachToSpy );527 view.unpin();528 view.hide();529 window.dispatchEvent( new Event( 'resize' ) );530 document.dispatchEvent( new Event( 'scroll' ) );531 view.show();532 window.dispatchEvent( new Event( 'resize' ) );533 document.dispatchEvent( new Event( 'scroll' ) );534 sinon.assert.calledOnce( attachToSpy );535 } );536 } );537 } );538 describe( 'defaultPositions', () => {539 let positions, balloonRect, targetRect, viewportRect, arrowHOffset, arrowVOffset;540 beforeEach( () => {541 positions = BalloonPanelView.defaultPositions;542 arrowHOffset = BalloonPanelView.arrowHorizontalOffset;543 arrowVOffset = BalloonPanelView.arrowVerticalOffset;544 viewportRect = new Rect( {545 top: 0,546 bottom: 0,547 left: 0,548 right: 0,549 width: 200,550 height: 200551 } );552 targetRect = new Rect( {553 top: 100,554 bottom: 200,555 left: 100,556 right: 200,557 width: 100,558 height: 100559 } );560 balloonRect = new Rect( {561 top: 0,562 bottom: 0,563 left: 0,564 right: 0,565 width: 50,566 height: 50567 } );568 } );569 it( 'should have a proper length', () => {570 expect( Object.keys( positions ) ).to.have.length( 31 );571 } );572 // ------- North573 it( 'should define the "northArrowSouth" position', () => {574 expect( positions.northArrowSouth( targetRect, balloonRect ) ).to.deep.equal( {575 top: 50 - arrowVOffset,576 left: 125,577 name: 'arrow_s'578 } );579 } );580 it( 'should define the "northArrowSouthEast" position', () => {581 expect( positions.northArrowSouthEast( targetRect, balloonRect ) ).to.deep.equal( {582 top: 50 - arrowVOffset,583 left: 100 + arrowHOffset,584 name: 'arrow_se'585 } );586 } );587 it( 'should define the "northArrowSouthMiddleEast" position', () => {588 expect( positions.northArrowSouthMiddleEast( targetRect, balloonRect ) ).to.deep.equal( {589 top: 50 - arrowVOffset,590 left: 112.5 + arrowHOffset,591 name: 'arrow_sme'592 } );593 } );594 it( 'should define the "northArrowSouthWest" position', () => {595 expect( positions.northArrowSouthWest( targetRect, balloonRect ) ).to.deep.equal( {596 top: 50 - arrowVOffset,597 left: 150 - arrowHOffset,598 name: 'arrow_sw'599 } );600 } );601 it( 'should define the "northArrowSouthMiddleWest" position', () => {602 expect( positions.northArrowSouthMiddleWest( targetRect, balloonRect ) ).to.deep.equal( {603 top: 50 - arrowVOffset,604 left: 137.5 - arrowHOffset,605 name: 'arrow_smw'606 } );607 } );608 // ------- North west609 it( 'should define the "northWestArrowSouth" position', () => {610 expect( positions.northWestArrowSouth( targetRect, balloonRect ) ).to.deep.equal( {611 top: 50 - arrowVOffset,612 left: 75,613 name: 'arrow_s'614 } );615 } );616 it( 'should define the "northWestArrowSouthWest" position', () => {617 expect( positions.northWestArrowSouthWest( targetRect, balloonRect ) ).to.deep.equal( {618 top: 50 - arrowVOffset,619 left: 100 - arrowHOffset,620 name: 'arrow_sw'621 } );622 } );623 it( 'should define the "northWestArrowSouthMiddleWest" position', () => {624 expect( positions.northWestArrowSouthMiddleWest( targetRect, balloonRect ) ).to.deep.equal( {625 top: 50 - arrowVOffset,626 left: 87.5 - arrowHOffset,627 name: 'arrow_smw'628 } );629 } );630 it( 'should define the "northWestArrowSouthEast" position', () => {631 expect( positions.northWestArrowSouthEast( targetRect, balloonRect ) ).to.deep.equal( {632 top: 50 - arrowVOffset,633 left: 50 + arrowHOffset,634 name: 'arrow_se'635 } );636 } );637 it( 'should define the "northWestArrowSouthMiddleEast" position', () => {638 expect( positions.northWestArrowSouthMiddleEast( targetRect, balloonRect ) ).to.deep.equal( {639 top: 50 - arrowVOffset,640 left: 62.5 + arrowHOffset,641 name: 'arrow_sme'642 } );643 } );644 // ------- North east645 it( 'should define the "northEastArrowSouth" position', () => {646 expect( positions.northEastArrowSouth( targetRect, balloonRect ) ).to.deep.equal( {647 top: 50 - arrowVOffset,648 left: 175,649 name: 'arrow_s'650 } );651 } );652 it( 'should define the "northEastArrowSouthEast" position', () => {653 expect( positions.northEastArrowSouthEast( targetRect, balloonRect ) ).to.deep.equal( {654 top: 50 - arrowVOffset,655 left: 150 + arrowHOffset,656 name: 'arrow_se'657 } );658 } );659 it( 'should define the "northEastArrowSouthMiddleEast" position', () => {660 expect( positions.northEastArrowSouthMiddleEast( targetRect, balloonRect ) ).to.deep.equal( {661 top: 50 - arrowVOffset,662 left: 162.5 + arrowHOffset,663 name: 'arrow_sme'664 } );665 } );666 it( 'should define the "northEastArrowSouthWest" position', () => {667 expect( positions.northEastArrowSouthWest( targetRect, balloonRect ) ).to.deep.equal( {668 top: 50 - arrowVOffset,669 left: 200 - arrowHOffset,670 name: 'arrow_sw'671 } );672 } );673 it( 'should define the "northEastArrowSouthMiddleWest" position', () => {674 expect( positions.northEastArrowSouthMiddleWest( targetRect, balloonRect ) ).to.deep.equal( {675 top: 50 - arrowVOffset,676 left: 187.5 - arrowHOffset,677 name: 'arrow_smw'678 } );679 } );680 // ------- South681 it( 'should define the "southArrowNorth" position', () => {682 expect( positions.southArrowNorth( targetRect, balloonRect ) ).to.deep.equal( {683 top: 200 + arrowVOffset,684 left: 125,685 name: 'arrow_n'686 } );687 } );688 it( 'should define the "southArrowNorthEast" position', () => {689 expect( positions.southArrowNorthEast( targetRect, balloonRect ) ).to.deep.equal( {690 top: 200 + arrowVOffset,691 left: 100 + arrowHOffset,692 name: 'arrow_ne'693 } );694 } );695 it( 'should define the "southArrowNorthMiddleEast" position', () => {696 expect( positions.southArrowNorthMiddleEast( targetRect, balloonRect ) ).to.deep.equal( {697 top: 200 + arrowVOffset,698 left: 112.5 + arrowHOffset,699 name: 'arrow_nme'700 } );701 } );702 it( 'should define the "southArrowNorthWest" position', () => {703 expect( positions.southArrowNorthWest( targetRect, balloonRect ) ).to.deep.equal( {704 top: 200 + arrowVOffset,705 left: 150 - arrowHOffset,706 name: 'arrow_nw'707 } );708 } );709 it( 'should define the "southArrowNorthMiddleWest" position', () => {710 expect( positions.southArrowNorthMiddleWest( targetRect, balloonRect ) ).to.deep.equal( {711 top: 200 + arrowVOffset,712 left: 137.5 - arrowHOffset,713 name: 'arrow_nmw'714 } );715 } );716 // ------- South west717 it( 'should define the "southWestArrowNorth" position', () => {718 expect( positions.southWestArrowNorth( targetRect, balloonRect ) ).to.deep.equal( {719 top: 200 + arrowVOffset,720 left: 75,721 name: 'arrow_n'722 } );723 } );724 it( 'should define the "southWestArrowNorthWest" position', () => {725 expect( positions.southWestArrowNorthWest( targetRect, balloonRect ) ).to.deep.equal( {726 top: 200 + arrowVOffset,727 left: 100 - arrowHOffset,728 name: 'arrow_nw'729 } );730 } );731 it( 'should define the "southWestArrowNorthMiddleWest" position', () => {732 expect( positions.southWestArrowNorthMiddleWest( targetRect, balloonRect ) ).to.deep.equal( {733 top: 200 + arrowVOffset,734 left: 87.5 - arrowHOffset,735 name: 'arrow_nmw'736 } );737 } );738 it( 'should define the "southWestArrowNorthEast" position', () => {739 expect( positions.southWestArrowNorthEast( targetRect, balloonRect ) ).to.deep.equal( {740 top: 200 + arrowVOffset,741 left: 50 + arrowHOffset,742 name: 'arrow_ne'743 } );744 } );745 it( 'should define the "southWestArrowNorthMiddleEast" position', () => {746 expect( positions.southWestArrowNorthMiddleEast( targetRect, balloonRect ) ).to.deep.equal( {747 top: 200 + arrowVOffset,748 left: 62.5 + arrowHOffset,749 name: 'arrow_nme'750 } );751 } );752 // ------- South east753 it( 'should define the "southEastArrowNorth" position', () => {754 expect( positions.southEastArrowNorth( targetRect, balloonRect ) ).to.deep.equal( {755 top: 200 + arrowVOffset,756 left: 175,757 name: 'arrow_n'758 } );759 } );760 it( 'should define the "southEastArrowNorthEast" position', () => {761 expect( positions.southEastArrowNorthEast( targetRect, balloonRect ) ).to.deep.equal( {762 top: 200 + arrowVOffset,763 left: 150 + arrowHOffset,764 name: 'arrow_ne'765 } );766 } );767 it( 'should define the "southEastArrowNorthMiddleEast" position', () => {768 expect( positions.southEastArrowNorthMiddleEast( targetRect, balloonRect ) ).to.deep.equal( {769 top: 200 + arrowVOffset,770 left: 162.5 + arrowHOffset,771 name: 'arrow_nme'772 } );773 } );774 it( 'should define the "southEastArrowNorthWest" position', () => {775 expect( positions.southEastArrowNorthWest( targetRect, balloonRect ) ).to.deep.equal( {776 top: 200 + arrowVOffset,777 left: 200 - arrowHOffset,778 name: 'arrow_nw'779 } );780 } );781 it( 'should define the "southEastArrowNorthMiddleWest" position', () => {782 expect( positions.southEastArrowNorthMiddleWest( targetRect, balloonRect ) ).to.deep.equal( {783 top: 200 + arrowVOffset,784 left: 187.5 - arrowHOffset,785 name: 'arrow_nmw'786 } );787 } );788 // ------- Sticky789 it( 'should define the "viewportStickyNorth" position and return null if not sticky', () => {790 expect( positions.viewportStickyNorth( targetRect, balloonRect, viewportRect ) ).to.equal( null );791 } );792 } );793 describe( 'stickyPositions', () => {794 let positions, balloonRect, targetRect, viewportRect, stickyOffset;795 beforeEach( () => {796 positions = BalloonPanelView.defaultPositions;797 stickyOffset = BalloonPanelView.stickyVerticalOffset;798 balloonRect = new Rect( {799 top: 0,800 bottom: 0,801 left: 0,802 right: 0,803 width: 50,804 height: 50805 } );806 } );807 it( 'should stick position to the top when top position of the element is above the viewport and the element' +808 'area intersects with the viewport area', () => {809 viewportRect = new Rect( {810 top: 300,811 bottom: 800,812 left: 0,813 right: 200,814 width: 0,815 height: 0816 } );817 targetRect = new Rect( {818 top: 200,819 bottom: 400,820 left: 50,821 right: 100,822 width: 0,823 height: 0824 } );825 expect( positions.viewportStickyNorth( targetRect, balloonRect, viewportRect ) ).to.deep.equal( {826 top: 300 + stickyOffset,827 left: 25,828 name: 'arrowless',829 config: {830 withArrow: false831 }832 } );833 } );834 it( 'should return null if not sticky because element is fully outside of the viewport', () => {835 viewportRect = new Rect( {836 top: 200,837 bottom: 0,838 left: 0,839 right: 0,840 width: 200,841 height: 200842 } );843 targetRect = new Rect( {844 top: 0,845 bottom: 0,846 left: 0,847 right: 0,848 width: 100,849 height: 100850 } );851 expect( positions.viewportStickyNorth( targetRect, balloonRect, viewportRect ) ).to.equal( null );852 } );853 } );854 describe( 'generatePositions()', () => {855 let defaultPositions, balloonRect, targetRect, viewportRect;856 beforeEach( () => {857 defaultPositions = BalloonPanelView.defaultPositions;858 viewportRect = new Rect( {859 top: 300,860 bottom: 800,861 left: 0,862 right: 200,863 width: 0,864 height: 0865 } );866 targetRect = new Rect( {867 top: 200,868 bottom: 400,869 left: 50,870 right: 100,871 width: 0,872 height: 0873 } );874 balloonRect = new Rect( {875 top: 0,876 bottom: 0,877 left: 0,878 right: 0,879 width: 50,880 height: 50881 } );882 } );883 it( 'should generate the same set of positions as BalloonPanelView#defaultPositions when no options specified', () => {884 const generatedPositions = generatePositions();885 for ( const name in generatedPositions ) {886 const generatedResult = generatedPositions[ name ]( targetRect, balloonRect, viewportRect );887 const defaultResult = defaultPositions[ name ]( targetRect, balloonRect, viewportRect );888 expect( generatedResult ).to.deep.equal( defaultResult, name );889 }890 } );891 it( 'should respect the "horizontalOffset" option', () => {892 const generatedPositions = generatePositions( {893 horizontalOffset: BalloonPanelView.arrowHorizontalOffset + 100894 } );895 for ( const name in generatedPositions ) {896 const generatedResult = generatedPositions[ name ]( targetRect, balloonRect, viewportRect );897 if ( name.match( /Arrow(South|North)(.+)?East/ ) ) {898 generatedResult.left -= 100;899 } else if ( name.match( /Arrow(South|North)(.+)?West/ ) ) {900 generatedResult.left += 100;901 }902 const defaultResult = defaultPositions[ name ]( targetRect, balloonRect, viewportRect );903 expect( generatedResult ).to.deep.equal( defaultResult, name );904 }905 } );906 it( 'should respect the "verticalOffset" option', () => {907 const generatedPositions = generatePositions( {908 verticalOffset: BalloonPanelView.arrowVerticalOffset + 100909 } );910 for ( const name in generatedPositions ) {911 const generatedResult = generatedPositions[ name ]( targetRect, balloonRect, viewportRect );912 if ( name.match( /^south/ ) ) {913 generatedResult.top -= 100;914 } else if ( name.match( /^north/ ) ) {915 generatedResult.top += 100;916 }917 const defaultResult = defaultPositions[ name ]( targetRect, balloonRect, viewportRect );918 expect( generatedResult ).to.deep.equal( defaultResult, name );919 }920 } );921 it( 'should respect the "stickyVerticalOffset" option', () => {922 const generatedPositions = generatePositions( {923 stickyVerticalOffset: BalloonPanelView.stickyVerticalOffset + 100924 } );925 for ( const name in generatedPositions ) {926 const generatedResult = generatedPositions[ name ]( targetRect, balloonRect, viewportRect );927 if ( name.match( /sticky/i ) ) {928 generatedResult.top -= 100;929 }930 const defaultResult = defaultPositions[ name ]( targetRect, balloonRect, viewportRect );931 expect( generatedResult ).to.deep.equal( defaultResult, name );932 }933 } );934 it( 'should respect the "config" option', () => {935 const generatedPositions = generatePositions( {936 config: {937 foo: 'bar',938 withArrow: true939 }940 } );941 for ( const name in generatedPositions ) {942 const generatedResult = generatedPositions[ name ]( targetRect, balloonRect, viewportRect );943 expect( generatedResult.config ).to.deep.equal( {944 foo: 'bar',945 withArrow: true946 }, name );947 }948 } );949 } );950} );951function mockBoundingBox( element, data ) {952 const boundingBox = Object.assign( {}, data );953 boundingBox.right = boundingBox.left + boundingBox.width;954 boundingBox.bottom = boundingBox.top + boundingBox.height;955 testUtils.sinon.stub( element, 'getBoundingClientRect' ).returns( boundingBox );...
Using AI Code Generation
1function test() {2 var wpt = new WebPageTest('www.webpagetest.org');3 wpt.runTest(url, function(err, data) {4 if (err) return console.log(err);5 wpt.getPositionedAncestor(data.data.testId, function(err, data) {6 if (err) return console.log(err);7 console.log(data);8 });9 });10}11test();12function test() {13 var wpt = new WebPageTest('www.webpagetest.org');14 wpt.runTest(url, function(err, data) {15 if (err) return console.log(err);16 wpt.getBreakdown(data.data.testId, function(err, data) {17 if (err) return console.log(err);18 console.log(data);19 });20 });21}22test();23function test() {24 var wpt = new WebPageTest('www.webpagetest.org');25 wpt.runTest(url, function(err, data) {26 if (err) return console.log(err);27 wpt.getRequests(data.data.testId, function(err, data) {28 if (err) return console.log(err);29 console.log(data);30 });31 });32}33test();
Using AI Code Generation
1function test() {2 var testDiv = document.getElementById("testDiv");3 var positionedAncestor = wpt.dom.positionedAncestor(testDiv);4 if (positionedAncestor != null) {5 alert("positionedAncestor is " + positionedAncestor.id);6 }7 else {8 alert("positionedAncestor is null");9 }10}11 <div id="testDiv" style="position:relative;">12 <div id="testDiv1" style="position:absolute;">13 <div id="testDiv2" style="position:static;">14 <div id="testDiv3" style="position:fixed;">15 <div id="testDiv4" style="position:relative;">16 <div id="testDiv5" style="position:absolute;">17 <div id="testDiv6" style="position:static;">18 <div id="testDiv7" style="position:fixed;">19 <div id="testDiv8" style="position:relative;">20 <div id="testDiv9" style="position:absolute;">21 <div id="testDiv10" style="position:static;">22 <div id="testDiv11" style="position:fixed;">23 <div id="testDiv12" style="position:relative;">24 <div id="testDiv13" style="position:absolute;">25 <div id="testDiv14" style="position:static;">26 <div id="testDiv15" style="position:fixed;">27 <div id="testDiv16" style="position:relative;">28 <div id="testDiv17" style="position:absolute;">29 <div id="testDiv18" style="position:static;">30 <div id="testDiv19" style="position:fixed;">31 <div id="testDiv20" style="position:relative;">32 <div id="testDiv21" style="position:absolute;">33 <div id="testDiv22" style="position:static;">34 <div id="testDiv23" style="position:fixed;">35 <div id="testDiv24" style="position:relative;">
Using AI Code Generation
1var positionedAncestor = CKEDITOR.plugins.wptextpattern.positionedAncestor;2var editor = CKEDITOR.instances.editor1;3var range = editor.getSelection().getRanges()[0];4var element = positionedAncestor( range.startContainer );5console.log( element.$.nodeName );6var getWordRange = CKEDITOR.plugins.wptextpattern.getWordRange;7var editor = CKEDITOR.instances.editor1;8var range = editor.getSelection().getRanges()[0];9var wordRange = getWordRange( range.startContainer, range.startOffset );10console.log( wordRange.startOffset );11var getWord = CKEDITOR.plugins.wptextpattern.getWord;12var editor = CKEDITOR.instances.editor1;13var range = editor.getSelection().getRanges()[0];14var word = getWord( range.startContainer, range.startOffset );15console.log( word );16var getWord = CKEDITOR.plugins.wptextpattern.getWord;17var editor = CKEDITOR.instances.editor1;18var range = editor.getSelection().getRanges()[0];19var word = getWord( range.startContainer, range.startOffset );20console.log( word );21var getWord = CKEDITOR.plugins.wptextpattern.getWord;22var editor = CKEDITOR.instances.editor1;23var range = editor.getSelection().getRanges()[0];24var word = getWord( range.startContainer, range.startOffset );25console.log( word );
Using AI Code Generation
1test(function() {2 var div = document.getElementById("div1");3 assert_equals(div.positionedAncestor(), document.body);4}, "positionedAncestor method of wpt test");5test(function() {6 var div = document.getElementById("div2");7 assert_equals(div.positionedAncestor(), document.body);8}, "positionedAncestor method of wpt test");9test(function() {10 var div = document.getElementById("div3");11 assert_equals(div.positionedAncestor(), document.body);12}, "positionedAncestor method of wpt test");13test(function() {14 var div = document.getElementById("div4");15 assert_equals(div.positionedAncestor(), document.body);16}, "positionedAncestor method of wpt test");17test(function() {18 var div = document.getElementById("div5");19 assert_equals(div.positionedAncestor(), document.body);20}, "positionedAncestor method of wpt test");21test(function() {22 var div = document.getElementById("div6");23 assert_equals(div.positionedAncestor(), document.body);24}, "positionedAncestor method of wpt test");25test(function() {26 var div = document.getElementById("div7");27 assert_equals(div.positionedAncestor(), document.body);28}, "positionedAncestor method of wpt test");29test(function() {30 var div = document.getElementById("div8");31 assert_equals(div.positionedAncestor(), document.body);32}, "positionedAncestor method of wpt test");33test(function() {34 var div = document.getElementById("div9");35 assert_equals(div.positionedAncestor(), document.body);36}, "positionedAncestor method of wpt test");
Using AI Code Generation
1var element = document.getElementById('wptb-element-dummy-id-1');2var positionedAncestor = element.positionedAncestor();3console.log(positionedAncestor.id);4WPTB_Element.prototype.positionedAncestor = function() {5 var element = this;6 var positionedAncestor;7 while (element) {8 if (element.positioned()) {9 positionedAncestor = element;10 break;11 }12 element = element.parent();13 }14 return positionedAncestor;15};16WPTB_Element.prototype.positioned = function() {17 var element = this;18 var style = window.getComputedStyle(element.element);19 return (style.position === 'relative' || style.position === 'absolute');20};21WPTB_Element.prototype.parent = function() {22 var element = this;23 var parentElement = element.element.parentElement;24 if (parentElement && parentElement.classList.contains('wptb-ph-element')) {25 parentElement = parentElement.parentElement;26 }27 return parentElement ? new WPTB_Element(parentElement) : null;28};29WPTB_Element.prototype.getStyle = function (property) {30 var element = this;31 var style = window.getComputedStyle(element.element);32 return style[property];33};34WPTB_Element.prototype.getStyle = function (property) {35 var element = this;36 var style = window.getComputedStyle(element.element);37 return style[property];38};39WPTB_Element.prototype.getStyle = function (property) {40 var element = this;41 var style = window.getComputedStyle(element.element);42 return style[property];43};44WPTB_Element.prototype.getStyle = function (property) {45 var element = this;
Using AI Code Generation
1var myAncestor = positionedAncestor( document.getElementById( 'myDiv' ) );2alert( myAncestor.id );3var myElems = getElementsByClassName( 'myClass' );4for( var i = 0; i < myElems.length; i++ ) {5 alert( myElems[i].id );6}7var myElems = getElementsByClassName( 'myClass' );8for( var i = 0; i < myElems.length; i++ ) {9 alert( myElems[i].id );10}11var myElems = getElementsByClassName( 'myClass' );12for( var i = 0; i < myElems.length; i++ ) {13 alert( myElems[i].id );14}15var myElems = getElementsByClassName( 'myClass' );16for( var i = 0; i < myElems.length; i++ ) {17 alert( myElems[i].id );18}19var myElems = getElementsByClassName( 'myClass' );20for( var i = 0; i < myElems.length; i++ ) {21 alert( myElems[i].id );22}23var myElems = getElementsByClassName( 'myClass' );24for( var i = 0; i < myElems.length; i++ ) {25 alert( myElems[i].id );26}27var myElems = getElementsByClassName( 'myClass' );28for( var i = 0; i < myElems.length; i++ ) {29 alert( myElems[i].id );30}31var myElems = getElementsByClassName( 'myClass' );32for( var i = 0; i < myElems.length; i++ ) {33 alert( myElems[i].id );34}
Using AI Code Generation
1var wpt = require('wpt.js');2var ancestor = wpt.positionedAncestor(document.getElementById('myDiv'));3console.log(ancestor.tagName);4console.log(ancestor.id);5console.log(ancestor.className);6console.log(ancestor.style);7console.log(ancestor.style.position);8console.log(ancestor.style.left);9console.log(ancestor.style.top);10console.log(ancestor.style.width);11console.log(ancestor.style.height);12console.log(ancestor.style.zIndex);13console.log(ancestor.style.overflow);14console.log(ancestor.style.overflowX);15console.log(ancestor.style.overflowY);16console.log(ancestor.style.visibility);17console.log(ancestor.style.display);18console.log(ancestor.style.opacity);19console.log(ancestor.style.filter);20console.log(ancestor.style.transform);21console.log(ancestor.style.transformOrigin);22console.log(ancestor.style.transformStyle);23console.log(ancestor.style.backfaceVisibility);24console.log(ancestor.style.perspective);25console.log(ancestor.style.perspectiveOrigin);26console.log(ancestor.style.transition);27console.log(ancestor.style.transitionDelay);28console.log(ancestor.style.transitionDuration);29console.log(ancestor.style.transitionProperty);30console.log(ancestor.style.transitionTimingFunction);31console.log(ancestor.style.webkit
Using AI Code Generation
1var ancestor = wpt.positionedAncestor();2if(ancestor == null){3 wpt.doSomething();4}else{5 wpt.doSomething();6}7var ancestor = element.positionedAncestor();8if(ancestor == null){9 element.doSomething();10}else{11 element.doSomething();12}
Using AI Code Generation
1var wptools = new Wptools();2var element = document.getElementById("test");3var parent = document.getElementById("parent");4wptools.positionedAncestor(element, parent);5element.style.position = "absolute";6element.style.top = "50px";7element.style.left = "50px";8element.style.width = "100px";9element.style.height = "100px";10element.style.backgroundColor = "red";11element.style.color = "white";12element.innerHTML = "test";13element.style.zIndex = "10";
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!