1410 | | // Append the view pane's height if align to top. |
1411 | | // Append element height if we are aligning to the bottom. |
1412 | | if ( alignTop ) |
1413 | | offset += winHeight; |
1414 | | else |
1415 | | { |
1416 | | offset += this.$.offsetHeight || 0; |
| 1417 | if ( overflowed ) |
| 1418 | this.scrollIntoParent( parent, alignToTop, 1 ); |
| 1419 | |
| 1420 | // Walk across the frame. |
| 1421 | if ( parent.is( 'html' ) ) |
| 1422 | { |
| 1423 | var win = parent.getWindow(); |
| 1424 | |
| 1425 | // Avoid security error. |
| 1426 | try |
| 1427 | { |
| 1428 | var iframe = win.$.frameElement; |
| 1429 | iframe && ( parent = new CKEDITOR.dom.element( iframe ) ); |
| 1430 | } |
| 1431 | catch(er){} |
| 1432 | } |
| 1433 | } |
| 1434 | while ( parent = parent.getParent() ); |
| 1435 | }, |
| 1436 | |
| 1437 | /** |
| 1438 | * Make any page element visible inside one of the ancestor by scrolling the parent. |
| 1439 | * @param {CKEDITOR.dom.element|CKEDITOR.dom.window} parent The container to scroll into. |
| 1440 | * @param {Boolean} [alignToTop] Align the element's top side with the container's |
| 1441 | * when "true" is specified, align the bottom with viewport bottom when "false" is specified, |
| 1442 | * other wise scroll on either side with the minimum amount to show the element. |
| 1443 | * @param {Boolean} [hscroll] Whether horizontal overflow should be considered. |
| 1444 | */ |
| 1445 | scrollIntoParent : function( parent, alignToTop, hscroll ) |
| 1446 | { |
| 1447 | !parent && ( parent = this.getWindow() ); |
| 1448 | |
| 1449 | var doc = parent.getDocument(); |
| 1450 | var isQuirks = doc.$.compatMode == 'BackCompat'; |
| 1451 | |
| 1452 | // On window <html> is scrolled while quirks scrolls <body>. |
| 1453 | if ( parent instanceof CKEDITOR.dom.window ) |
| 1454 | parent = isQuirks ? doc.getBody() : doc.getDocumentElement(); |
| 1455 | |
| 1456 | // Scroll the parent by the specified amount. |
| 1457 | function scrollBy( x, y ) |
| 1458 | { |
| 1459 | // Webkit doesn't support "scrollTop/scrollLeft" |
| 1460 | // on documentElement/body element. |
| 1461 | if ( /body|html/.test( parent.getName() ) ) |
| 1462 | parent.getWindow().$.scrollBy( x, y ); |
| 1463 | else |
| 1464 | { |
| 1465 | parent.$[ 'scrollLeft' ] += x; |
| 1466 | parent.$[ 'scrollTop' ] += y; |
| 1467 | } |
| 1468 | } |
1418 | | // Consider the margin in the scroll, which is ok for our current needs, but |
1419 | | // needs investigation if we will be using this function in other places. |
1420 | | offset += parseInt( this.getComputedStyle( 'marginBottom' ) || 0, 10 ) || 0; |
1421 | | } |
| 1470 | // Figure out the element position relative to the specified window. |
| 1471 | function screenPos( element, refWin ) |
| 1472 | { |
| 1473 | var pos = { x: 0, y: 0 }; |
| 1474 | |
| 1475 | if ( !( element.is( isQuirks ? 'body' : 'html' ) ) ) |
| 1476 | { |
| 1477 | var box = element.$.getBoundingClientRect(); |
| 1478 | pos.x = box.left, pos.y = box.top; |
| 1479 | } |
1430 | | // Scroll the window to the desired position, if not already visible(#3795). |
1431 | | var currentScroll = win.getScrollPosition().y; |
1432 | | if ( offset > currentScroll || offset < currentScroll - winHeight ) |
1433 | | win.$.scrollTo( 0, offset ); |
| 1491 | // calculated margin size. |
| 1492 | function margin( element, side ) |
| 1493 | { |
| 1494 | return parseInt( element.getComputedStyle( 'margin-' + side ) || 0, 10 ) || 0; |
| 1495 | } |
| 1496 | |
| 1497 | var win = parent.getWindow(); |
| 1498 | |
| 1499 | var thisPos = screenPos( this, win ), |
| 1500 | parentPos = screenPos( parent, win ), |
| 1501 | eh = this.$.offsetHeight, |
| 1502 | ew = this.$.offsetWidth, |
| 1503 | ch = parent.$.clientHeight, |
| 1504 | cw = parent.$.clientWidth, |
| 1505 | lt, |
| 1506 | br; |
| 1507 | |
| 1508 | // Left-top margins. |
| 1509 | lt = |
| 1510 | { |
| 1511 | x : thisPos.x - margin( this, 'left' ) - parentPos.x || 0, |
| 1512 | y : thisPos.y - margin( this, 'top' ) - parentPos.y|| 0 |
| 1513 | }; |
| 1514 | |
| 1515 | // Bottom-right margins. |
| 1516 | br = |
| 1517 | { |
| 1518 | x : thisPos.x + ew + margin( this, 'right' ) - ( ( parentPos.x ) + cw ) || 0, |
| 1519 | y : thisPos.y + eh + margin( this, 'bottom' ) - ( ( parentPos.y ) + ch ) || 0 |
| 1520 | }; |
| 1521 | |
| 1522 | // 1. Do the specified alignment as much as possible; |
| 1523 | // 2. Otherwise be smart to scroll only the minimum amount; |
| 1524 | // 3. Never cut at the top; |
| 1525 | // 4. DO NOT scroll when already visible. |
| 1526 | if ( lt.y < 0 || br.y > 0 ) |
| 1527 | { |
| 1528 | scrollBy( 0, |
| 1529 | alignToTop === true ? lt.y : |
| 1530 | alignToTop === false ? br.y : |
| 1531 | lt.y < 0 ? lt.y : br.y ); |
| 1532 | } |
| 1533 | |
| 1534 | if ( hscroll && ( lt.x < 0 || br.x > 0 ) ) |
| 1535 | scrollBy( lt.x < 0 ? lt.x : br.x, 0 ); |