X-Git-Url: https://jasonwoof.com/gitweb/?p=ckeditor.git;a=blobdiff_plain;f=_source%2Fcore%2Fdom%2Felement.js;h=c83674ab405ebf54b9778ffdc6acdaced3c50a96;hp=7adb189839645c3d3a3ceecaba95a16ed7247953;hb=2f22c0c38f17e75be5541089076885442aaa2377;hpb=e73319a12b56100b29ef456fd74114fe5519e01c diff --git a/_source/core/dom/element.js b/_source/core/dom/element.js index 7adb189..c83674a 100644 --- a/_source/core/dom/element.js +++ b/_source/core/dom/element.js @@ -1,5 +1,5 @@ /* -Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved. +Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.html or http://ckeditor.com/license */ @@ -580,7 +580,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, * in the future. * @returns {String} The text value. * @example - * var element = CKEDITOR.dom.element.createFromHtml( '<div>Same <i>text</i>.</div>' ); + * var element = CKEDITOR.dom.element.createFromHtml( '<div>Sample <i>text</i>.</div>' ); * alert( element.getText() ); // "Sample text." */ getText : function() @@ -730,6 +730,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, if ( this.isReadOnly() || this.getComputedStyle( 'display' ) == 'none' || this.getComputedStyle( 'visibility' ) == 'hidden' + || this.is( 'a' ) && this.data( 'cke-saved-name' ) && !this.getChildCount() || CKEDITOR.dtd.$nonEditable[ name ] ) { return false; @@ -1261,12 +1262,13 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, if ( CKEDITOR.env.ie || CKEDITOR.env.opera ) { var element = this.$, + elements = element.getElementsByTagName("*"), e, i = 0; element.unselectable = 'on'; - while ( ( e = element.all[ i++ ] ) ) + while ( ( e = elements[ i++ ] ) ) { switch ( e.tagName.toLowerCase() ) { @@ -1396,40 +1398,143 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, return { x : x, y : y }; }, - scrollIntoView : function( alignTop ) + /** + * Make any page element visible inside the browser viewport. + * @param {Boolean} [alignToTop] + */ + scrollIntoView : function( alignToTop ) { - // Get the element window. - var win = this.getWindow(), - winHeight = win.getViewPaneSize().height; - - // Starts from the offset that will be scrolled with the negative value of - // the visible window height. - var offset = winHeight * -1; - - // Append the view pane's height if align to top. - // Append element height if we are aligning to the bottom. - if ( alignTop ) - offset += winHeight; - else + var parent = this.getParent(); + if ( !parent ) return; + + // Scroll the element into parent container from the inner out. + do { - offset += this.$.offsetHeight || 0; + // Check ancestors that overflows. + var overflowed = + parent.$.clientWidth && parent.$.clientWidth < parent.$.scrollWidth + || parent.$.clientHeight && parent.$.clientHeight < parent.$.scrollHeight; + + if ( overflowed ) + this.scrollIntoParent( parent, alignToTop, 1 ); + + // Walk across the frame. + if ( parent.is( 'html' ) ) + { + var win = parent.getWindow(); - // Consider the margin in the scroll, which is ok for our current needs, but - // needs investigation if we will be using this function in other places. - offset += parseInt( this.getComputedStyle( 'marginBottom' ) || 0, 10 ) || 0; + // Avoid security error. + try + { + var iframe = win.$.frameElement; + iframe && ( parent = new CKEDITOR.dom.element( iframe ) ); + } + catch(er){} + } } + while ( ( parent = parent.getParent() ) ); + }, - // Append the offsets for the entire element hierarchy. - var elementPosition = this.getDocumentPosition(); - offset += elementPosition.y; + /** + * Make any page element visible inside one of the ancestors by scrolling the parent. + * @param {CKEDITOR.dom.element|CKEDITOR.dom.window} parent The container to scroll into. + * @param {Boolean} [alignToTop] Align the element's top side with the container's + * when true is specified; align the bottom with viewport bottom when + * false is specified. Otherwise scroll on either side with the minimum + * amount to show the element. + * @param {Boolean} [hscroll] Whether horizontal overflow should be considered. + */ + scrollIntoParent : function( parent, alignToTop, hscroll ) + { + !parent && ( parent = this.getWindow() ); + + var doc = parent.getDocument(); + var isQuirks = doc.$.compatMode == 'BackCompat'; - // offset value might be out of range(nagative), fix it(#3692). - offset = offset < 0 ? 0 : offset; + // On window is scrolled while quirks scrolls . + if ( parent instanceof CKEDITOR.dom.window ) + parent = isQuirks ? doc.getBody() : doc.getDocumentElement(); + + // Scroll the parent by the specified amount. + function scrollBy( x, y ) + { + // Webkit doesn't support "scrollTop/scrollLeft" + // on documentElement/body element. + if ( /body|html/.test( parent.getName() ) ) + parent.getWindow().$.scrollBy( x, y ); + else + { + parent.$[ 'scrollLeft' ] += x; + parent.$[ 'scrollTop' ] += y; + } + } + + // Figure out the element position relative to the specified window. + function screenPos( element, refWin ) + { + var pos = { x: 0, y: 0 }; + + if ( !( element.is( isQuirks ? 'body' : 'html' ) ) ) + { + var box = element.$.getBoundingClientRect(); + pos.x = box.left, pos.y = box.top; + } + + var win = element.getWindow(); + if ( !win.equals( refWin ) ) + { + var outerPos = screenPos( CKEDITOR.dom.element.get( win.$.frameElement ), refWin ); + pos.x += outerPos.x, pos.y += outerPos.y; + } + + return pos; + } + + // calculated margin size. + function margin( element, side ) + { + return parseInt( element.getComputedStyle( 'margin-' + side ) || 0, 10 ) || 0; + } + + var win = parent.getWindow(); + + var thisPos = screenPos( this, win ), + parentPos = screenPos( parent, win ), + eh = this.$.offsetHeight, + ew = this.$.offsetWidth, + ch = parent.$.clientHeight, + cw = parent.$.clientWidth, + lt, + br; + + // Left-top margins. + lt = + { + x : thisPos.x - margin( this, 'left' ) - parentPos.x || 0, + y : thisPos.y - margin( this, 'top' ) - parentPos.y|| 0 + }; + + // Bottom-right margins. + br = + { + x : thisPos.x + ew + margin( this, 'right' ) - ( ( parentPos.x ) + cw ) || 0, + y : thisPos.y + eh + margin( this, 'bottom' ) - ( ( parentPos.y ) + ch ) || 0 + }; + + // 1. Do the specified alignment as much as possible; + // 2. Otherwise be smart to scroll only the minimum amount; + // 3. Never cut at the top; + // 4. DO NOT scroll when already visible. + if ( lt.y < 0 || br.y > 0 ) + { + scrollBy( 0, + alignToTop === true ? lt.y : + alignToTop === false ? br.y : + lt.y < 0 ? lt.y : br.y ); + } - // Scroll the window to the desired position, if not already visible(#3795). - var currentScroll = win.getScrollPosition().y; - if ( offset > currentScroll || offset < currentScroll - winHeight ) - win.$.scrollTo( 0, offset ); + if ( hscroll && ( lt.x < 0 || br.x > 0 ) ) + scrollBy( lt.x < 0 ? lt.x : br.x, 0 ); }, setState : function( state )