X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=_source%2Fcore%2Fdom%2Felement.js;h=2f3eb0ad8e3c7effbbc17252df9a8252da97a6a3;hb=4e90e78dc97789709ee7404359a5517540c27553;hp=77031f07f3ebeac03bdf5d4df72f00025ca01d89;hpb=c9fdde67e6384bd5a66adc2b3bba5c4ce9db56c7;p=ckeditor.git diff --git a/_source/core/dom/element.js b/_source/core/dom/element.js index 77031f0..2f3eb0a 100644 --- a/_source/core/dom/element.js +++ b/_source/core/dom/element.js @@ -1,5 +1,5 @@ /* -Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. +Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.html or http://ckeditor.com/license */ @@ -88,7 +88,7 @@ CKEDITOR.dom.element.setMarker = function( database, element, name, value ) CKEDITOR.dom.element.clearAllMarkers = function( database ) { for ( var i in database ) - CKEDITOR.dom.element.clearMarkers( database, database[i], true ); + CKEDITOR.dom.element.clearMarkers( database, database[i], 1 ); }; CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatabase ) @@ -307,12 +307,17 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, /** * Moves the selection focus to this element. + * @function + * @param {Boolean} defer Whether to asynchronously defer the + * execution by 100 ms. * @example * var element = CKEDITOR.document.getById( 'myTextarea' ); * element.focus(); */ - focus : function() + focus : ( function() { + function exec() + { // IE throws error if the element is not visible. try { @@ -320,7 +325,16 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, } catch (e) {} - }, + } + + return function( defer ) + { + if ( defer ) + CKEDITOR.tools.setTimeout( exec, 100, this ); + else + exec.call( this ); + }; + })(), /** * Gets the inner HTML of this element. @@ -439,7 +453,8 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, } case 'hspace': - return this.$.hspace; + case 'value': + return this.$[ name ]; case 'style': // IE does not return inline styles via getAttribute(). See #2947. @@ -613,7 +628,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, // Cache the lowercased name inside a closure. var nodeName = this.$.nodeName.toLowerCase(); - if ( CKEDITOR.env.ie ) + if ( CKEDITOR.env.ie && ! ( document.documentMode > 8 ) ) { var scopeName = this.$.scopeName; if ( scopeName != 'HTML' ) @@ -721,14 +736,14 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, var thisLength = thisAttribs.length, otherLength = otherAttribs.length; - if ( !CKEDITOR.env.ie && thisLength != otherLength ) - return false; - for ( var i = 0 ; i < thisLength ; i++ ) { var attribute = thisAttribs[ i ]; - if ( ( !CKEDITOR.env.ie || ( attribute.specified && attribute.nodeName != '_cke_expando' ) ) && attribute.nodeValue != otherElement.getAttribute( attribute.nodeName ) ) + if ( attribute.nodeName == '_moz_dirty' ) + continue; + + if ( ( !CKEDITOR.env.ie || ( attribute.specified && attribute.nodeName != 'data-cke-expando' ) ) && attribute.nodeValue != otherElement.getAttribute( attribute.nodeName ) ) return false; } @@ -739,7 +754,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, for ( i = 0 ; i < otherLength ; i++ ) { attribute = otherAttribs[ i ]; - if ( attribute.specified && attribute.nodeName != '_cke_expando' + if ( attribute.specified && attribute.nodeName != 'data-cke-expando' && attribute.nodeValue != this.getAttribute( attribute.nodeName ) ) return false; } @@ -789,7 +804,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, { var child = children.getItem( i ); - if ( child.type == CKEDITOR.NODE_ELEMENT && child.getAttribute( '_cke_bookmark' ) ) + if ( child.type == CKEDITOR.NODE_ELEMENT && child.data( 'cke-bookmark' ) ) continue; if ( child.type == CKEDITOR.NODE_ELEMENT && !child.isEmptyInlineRemoveable() @@ -802,14 +817,15 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, }, /** - * Indicates that the element has defined attributes. + * Checks if the element has any defined attributes. + * @function * @returns {Boolean} True if the element has attributes. * @example - * var element = CKEDITOR.dom.element.createFromHtml( '
Example
' ); - * alert( element.hasAttributes() ); "true" + * var element = CKEDITOR.dom.element.createFromHtml( '<div title="Test">Example</div>' ); + * alert( element.hasAttributes() ); // "true" * @example - * var element = CKEDITOR.dom.element.createFromHtml( '
Example
' ); - * alert( element.hasAttributes() ); "false" + * var element = CKEDITOR.dom.element.createFromHtml( '<div>Example</div>' ); + * alert( element.hasAttributes() ); // "false" */ hasAttributes : CKEDITOR.env.ie && ( CKEDITOR.env.ie7Compat || CKEDITOR.env.ie6Compat ) ? @@ -834,7 +850,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, return true; // Attributes to be ignored. - case '_cke_expando' : + case 'data-cke-expando' : continue; /*jsl:fallthru*/ @@ -854,7 +870,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, attrsNum = attrs.length; // The _moz_dirty attribute might get into the element after pasting (#5455) - var execludeAttrs = { _cke_expando : 1, _moz_dirty : 1 }; + var execludeAttrs = { 'data-cke-expando' : 1, _moz_dirty : 1 }; return attrsNum > 0 && ( attrsNum > 2 || @@ -863,9 +879,9 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, }, /** - * Indicates whether a specified attribute is defined for this element. + * Checks if the specified attribute is defined for this element. * @returns {Boolean} True if the specified attribute is defined. - * @param (String) name The attribute name. + * @param {String} name The attribute name. * @example */ hasAttribute : function( name ) @@ -907,6 +923,14 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, } }, + /** + * Merges sibling elements that are identical to this one.
+ *
+ * Identical child elements are also merged. For example:
+ * <b><i></i></b><b><i></i></b> => <b><i></i></b> + * @function + * @param {Boolean} [inlineOnly] Allow only inline elements to be merged. Defaults to "true". + */ mergeSiblings : ( function() { function mergeElements( element, sibling, isNext ) @@ -917,7 +941,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, // queuing them to be moved later. (#5567) var pendingNodes = []; - while ( sibling.getAttribute( '_cke_bookmark' ) + while ( sibling.data( 'cke-bookmark' ) || sibling.isEmptyInlineRemoveable() ) { pendingNodes.push( sibling ); @@ -946,11 +970,14 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, } } - return function() + return function( inlineOnly ) { - // Merge empty links and anchors also. (#5567) - if ( !( CKEDITOR.dtd.$removeEmpty[ this.getName() ] || this.is( 'a' ) ) ) + if ( ! ( inlineOnly === false + || CKEDITOR.dtd.$removeEmpty[ this.getName() ] + || this.is( 'a' ) ) ) // Merge empty links and anchors also. (#5567) + { return; + } mergeElements( this, this.getNext(), true ); mergeElements( this, this.getPrevious() ); @@ -1170,13 +1197,13 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, function() { this.$.style.MozUserSelect = 'none'; - this.on( 'dragstart', function (evt) { evt.data.preventDefault(); } ); + this.on( 'dragstart', function( evt ) { evt.data.preventDefault(); } ); } : CKEDITOR.env.webkit ? function() { this.$.style.KhtmlUserSelect = 'none'; - this.on( 'dragstart', function (evt) { evt.data.preventDefault(); } ); + this.on( 'dragstart', function( evt ) { evt.data.preventDefault(); } ); } : function() @@ -1483,7 +1510,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, // Replace the node. this.getParent() && this.$.parentNode.replaceChild( newNode.$, this.$ ); - newNode.$._cke_expando = this.$._cke_expando; + newNode.$[ 'data-cke-expando' ] = this.$[ 'data-cke-expando' ]; this.$ = newNode.$; }, @@ -1525,32 +1552,85 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, }, /** - * Update the element's size with box model awareness. - * @name CKEDITOR.dom.element.setSize - * @param {String} type [width|height] - * @param {Number} size The length unit in px. - * @param isBorderBox Apply the {@param width} and {@param height} based on border box model. + * Gets element's direction. Supports both CSS 'direction' prop and 'dir' attr. */ - setSize : ( function() + getDirection : function( useComputed ) { - var sides = { - width : [ "border-left-width", "border-right-width","padding-left", "padding-right" ], - height : [ "border-top-width", "border-bottom-width", "padding-top", "padding-bottom" ] - }; + return useComputed ? this.getComputedStyle( 'direction' ) : this.getStyle( 'direction' ) || this.getAttribute( 'dir' ); + }, - return function( type, size, isBorderBox ) - { - if ( typeof size == 'number' ) - { - if ( isBorderBox && !( CKEDITOR.env.ie && CKEDITOR.env.quirks ) ) - { - var adjustment = 0; - for ( var i = 0, len = sides [ type ].length; i < len; i++ ) - adjustment += parseInt( this.getComputedStyle( sides [ type ][ i ] ) || 0, 10 ); - size -= adjustment; - } - this.setStyle( type, size + 'px' ); - } - }; - })() + /** + * Gets, sets and removes custom data to be stored as HTML5 data-* attributes. + * @param {String} name The name of the attribute, excluding the 'data-' part. + * @param {String} [value] The value to set. If set to false, the attribute will be removed. + * @example + * element.data( 'extra-info', 'test' ); // appended the attribute data-extra-info="test" to the element + * alert( element.data( 'extra-info' ) ); // "test" + * element.data( 'extra-info', false ); // remove the data-extra-info attribute from the element + */ + data : function ( name, value ) + { + name = 'data-' + name; + if ( value === undefined ) + return this.getAttribute( name ); + else if ( value === false ) + this.removeAttribute( name ); + else + this.setAttribute( name, value ); + + return null; + } }); + +( function() +{ + var sides = { + width : [ "border-left-width", "border-right-width","padding-left", "padding-right" ], + height : [ "border-top-width", "border-bottom-width", "padding-top", "padding-bottom" ] + }; + + function marginAndPaddingSize( type ) + { + var adjustment = 0; + for ( var i = 0, len = sides[ type ].length; i < len; i++ ) + adjustment += parseInt( this.getComputedStyle( sides [ type ][ i ] ) || 0, 10 ) || 0; + return adjustment; + } + + /** + * Sets the element size considering the box model. + * @name CKEDITOR.dom.element.prototype.setSize + * @function + * @param {String} type The dimension to set. It accepts "width" and "height". + * @param {Number} size The length unit in px. + * @param {Boolean} isBorderBox Apply the size based on the border box model. + */ + CKEDITOR.dom.element.prototype.setSize = function( type, size, isBorderBox ) + { + if ( typeof size == 'number' ) + { + if ( isBorderBox && !( CKEDITOR.env.ie && CKEDITOR.env.quirks ) ) + size -= marginAndPaddingSize.call( this, type ); + + this.setStyle( type, size + 'px' ); + } + }; + + /** + * Gets the element size, possibly considering the box model. + * @name CKEDITOR.dom.element.prototype.getSize + * @function + * @param {String} type The dimension to get. It accepts "width" and "height". + * @param {Boolean} isBorderBox Get the size based on the border box model. + */ + CKEDITOR.dom.element.prototype.getSize = function( type, isBorderBox ) + { + var size = Math.max( this.$[ 'offset' + CKEDITOR.tools.capitalize( type ) ], + this.$[ 'client' + CKEDITOR.tools.capitalize( type ) ] ) || 0; + + if ( isBorderBox ) + size -= marginAndPaddingSize.call( this, type ); + + return size; + }; +})();