Skip to content
Permalink
Browse files

Merge branch 't/11377' into major

  • Loading branch information...
mlewand committed Feb 7, 2014
2 parents b2281e5 + b5438df commit 587558325402187188f0e8f4c0f28e3de2754b33
Showing with 66 additions and 129 deletions.
  1. +1 −0 CHANGES.md
  2. +21 −33 plugins/link/dialogs/anchor.js
  3. +2 −10 plugins/link/dialogs/link.js
  4. +42 −86 plugins/link/plugin.js
@@ -5,6 +5,7 @@ CKEditor 4 Changelog

New Features:

* [#11377](http://dev.ckeditor.com/ticket/11377): Unify internal representation of empty anchors using fake objects.
* [#11225](http://dev.ckeditor.com/ticket/11225): Introduced the [`CKEDITOR.tools.transparentImageData`](http://localhost/cksource/ckeditor-docs/build/#!/api/CKEDITOR.tools-property-transparentImageData) property which contains transparent image data to be used in CSS or as images' source.

## CKEditor 4.3.3
@@ -12,8 +12,10 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) {
this.setValueOf( 'info', 'txtName', attributeValue || '' );
};

function createFakeAnchor( editor, anchor ) {
return editor.createFakeElement( anchor, 'cke_anchor', 'anchor' );
function createFakeAnchor( editor, attributes ) {
return editor.createFakeElement( editor.document.createElement( 'a', {
attributes: attributes
} ), 'cke_anchor', 'anchor' );
}

return {
@@ -30,8 +32,12 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) {

if ( this._.selectedElement ) {
if ( this._.selectedElement.data( 'cke-realelement' ) ) {
var newFake = createFakeAnchor( editor, editor.document.createElement( 'a', { attributes: attributes } ) );
var newFake = createFakeAnchor( editor, attributes );
newFake.replace( this._.selectedElement );

// Selecting fake element for IE. (#11377)
if ( CKEDITOR.env.ie )
editor.getSelection().selectElement( newFake );
} else
this._.selectedElement.setAttributes( attributes );
} else {
@@ -40,20 +46,7 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) {

// Empty anchor
if ( range.collapsed ) {
if ( CKEDITOR.plugins.link.synAnchorSelector )
attributes[ 'class' ] = 'cke_anchor_empty';

if ( CKEDITOR.plugins.link.emptyAnchorFix ) {
attributes[ 'contenteditable' ] = 'false';
attributes[ 'data-cke-editable' ] = 1;
}

var anchor = editor.document.createElement( 'a', { attributes: attributes } );

// Transform the anchor into a fake element for browsers that need it.
if ( CKEDITOR.plugins.link.fakeAnchor )
anchor = createFakeAnchor( editor, anchor );

var anchor = createFakeAnchor( editor, attributes );
range.insertNode( anchor );
} else {
if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 )
@@ -72,24 +65,19 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) {
},

onShow: function() {
var selection = editor.getSelection(),
fullySelected = selection.getSelectedElement(),
partialSelected;
var sel = editor.getSelection(),
fullySelected = sel.getSelectedElement(),
fakeSelected = fullySelected && fullySelected.data( 'cke-realelement' ),
linkElement = fakeSelected ?
CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, fullySelected ) :
CKEDITOR.plugins.link.getSelectedLink( editor );

if ( linkElement ) {
loadElements.call( this, linkElement );
!fakeSelected && sel.selectElement( linkElement );

// Detect the anchor under selection.
if ( fullySelected ) {
if ( CKEDITOR.plugins.link.fakeAnchor ) {
var realElement = CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, fullySelected );
realElement && loadElements.call( this, realElement );
if ( fullySelected )
this._.selectedElement = fullySelected;
} else if ( fullySelected.is( 'a' ) && fullySelected.hasAttribute( 'name' ) )
loadElements.call( this, fullySelected );
} else {
partialSelected = CKEDITOR.plugins.link.getSelectedLink( editor );
if ( partialSelected ) {
loadElements.call( this, partialSelected );
selection.selectElement( partialSelected );
}
}

this.getContentElement( 'info', 'txtName' ).focus();
@@ -1,4 +1,4 @@
/**
/**
* @license Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md or http://ckeditor.com/license
*/
@@ -197,7 +197,7 @@ CKEDITOR.dialog.add( 'link', function( editor ) {
advAttr( 'advTabIndex', 'tabindex' );
advAttr( 'advTitle', 'title' );
advAttr( 'advContentType', 'type' );
CKEDITOR.plugins.link.synAnchorSelector ? retval.adv.advCSSClasses = getLinkClass( element ) : advAttr( 'advCSSClasses', 'class' );
advAttr( 'advCSSClasses', 'class' );
advAttr( 'advCharset', 'charset' );
advAttr( 'advStyles', 'style' );
advAttr( 'advRel', 'rel' );
@@ -291,11 +291,6 @@ CKEDITOR.dialog.add( 'link', function( editor ) {
return 'String.fromCharCode(' + encodedChars.join( ',' ) + ')';
}

function getLinkClass( ele ) {
var className = ele.getAttribute( 'class' );
return className ? className.replace( /\s*(?:cke_anchor_empty|cke_anchor)(?:\s*$)?/g, '' ) : '';
}

var commonLang = editor.lang.common,
linkLang = editor.lang.link;

@@ -1204,9 +1199,6 @@ CKEDITOR.dialog.add( 'link', function( editor ) {
element.setAttributes( attributes );
element.removeAttributes( removeAttributes );

if ( data.adv && data.adv.advName && CKEDITOR.plugins.link.synAnchorSelector )
element.addClass( element.getChildCount() ? 'cke_anchor' : 'cke_anchor_empty' );

// Update text view when user changes protocol (#4612).
if ( href == textView || data.type == 'email' && textView.indexOf( '@' ) != -1 ) {
// Short mailto link text view (#5736).
@@ -1,4 +1,4 @@
/**
/**
* @license Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md or http://ckeditor.com/license
*/
@@ -23,14 +23,6 @@ CKEDITOR.plugins.add( 'link', {
// Show the arrow cursor for the anchor image (FF at least).
'cursor:auto;' +
'}' +
( CKEDITOR.plugins.link.synAnchorSelector ? ( 'a.cke_anchor_empty' +
'{' +
// Make empty anchor selectable on IE.
'display:inline-block;' +
// IE11 doesn't display empty inline-block elements.
( CKEDITOR.env.ie && CKEDITOR.env.version > 10 ? 'min-height:16px;vertical-align:middle' : '' ) +
'}'
) : '' ) +
'.%2 img.cke_anchor' +
'{' +
baseStyle +
@@ -164,60 +156,27 @@ CKEDITOR.plugins.add( 'link', {
},

afterInit: function( editor ) {
// Register a filter to displaying placeholders after mode change.

var dataProcessor = editor.dataProcessor,
dataFilter = dataProcessor && dataProcessor.dataFilter,
htmlFilter = dataProcessor && dataProcessor.htmlFilter,
pathFilters = editor._.elementsPath && editor._.elementsPath.filters;

if ( dataFilter ) {
dataFilter.addRules( {
elements: {
a: function( element ) {
var attributes = element.attributes;
if ( !attributes.name )
return null;

var isEmpty = !element.children.length;

if ( CKEDITOR.plugins.link.synAnchorSelector ) {
// IE needs a specific class name to be applied
// to the anchors, for appropriate styling.
var ieClass = isEmpty ? 'cke_anchor_empty' : 'cke_anchor';
var cls = attributes[ 'class' ];
if ( attributes.name && ( !cls || cls.indexOf( ieClass ) < 0 ) )
attributes[ 'class' ] = ( cls || '' ) + ' ' + ieClass;

if ( isEmpty && CKEDITOR.plugins.link.emptyAnchorFix ) {
attributes.contenteditable = 'false';
attributes[ 'data-cke-editable' ] = 1;
}
} else if ( CKEDITOR.plugins.link.fakeAnchor && isEmpty )
return editor.createFakeParserElement( element, 'cke_anchor', 'anchor' );

// Empty anchors upcasting to fake objects.
editor.dataProcessor.dataFilter.addRules( {
elements: {
a: function( element ) {
if ( !element.attributes.name )
return null;
}
}
} );
}

if ( CKEDITOR.plugins.link.emptyAnchorFix && htmlFilter ) {
htmlFilter.addRules( {
elements: {
a: function( element ) {
delete element.attributes.contenteditable;
}
if ( !element.children.length )
return editor.createFakeParserElement( element, 'cke_anchor', 'anchor' );

return null;
}
} );
}
}
} );

var pathFilters = editor._.elementsPath && editor._.elementsPath.filters;
if ( pathFilters ) {
pathFilters.push( function( element, name ) {
if ( name == 'a' ) {
if ( CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, element ) || ( element.getAttribute( 'name' ) && ( !element.getAttribute( 'href' ) || !element.getChildCount() ) ) )
return 'anchor';

}
} );
}
@@ -280,6 +239,7 @@ CKEDITOR.plugins.link = {
scope = ( editable.isInline() && !editor.plugins.divarea ) ? editor.document : editable,

links = scope.getElementsByTag( 'a' ),
imgs = scope.getElementsByTag( 'img' ),
anchors = [],
i = 0,
item;
@@ -293,50 +253,46 @@ CKEDITOR.plugins.link = {
} );
}
}

// Retrieve all "fake anchors" within the scope.
if ( this.fakeAnchor ) {
var imgs = scope.getElementsByTag( 'img' );

i = 0;
i = 0;

while ( ( item = imgs.getItem( i++ ) ) ) {
if ( ( item = this.tryRestoreFakeAnchor( editor, item ) ) ) {
anchors.push( {
name: item.getAttribute( 'name' ),
id: item.getAttribute( 'id' )
} );
}
while ( ( item = imgs.getItem( i++ ) ) ) {
if ( ( item = this.tryRestoreFakeAnchor( editor, item ) ) ) {
anchors.push( {
name: item.getAttribute( 'name' ),
id: item.getAttribute( 'id' )
} );
}
}

return anchors;
},

/**
* Opera and WebKit don't make it possible to select empty anchors. Fake
* elements must be used for them.
*
* @readonly
* @property {Boolean}
*/
fakeAnchor: CKEDITOR.env.opera || CKEDITOR.env.webkit,
* Opera and WebKit don't make it possible to select empty anchors. Fake
* elements must be used for them.
*
* @readonly
* @deprecated 4.3.3 It is set to `true` on every browser.
* @property {Boolean}
*/
fakeAnchor: true,

/**
* For browsers that don't support CSS3 `a[name]:empty()`, note IE9 is included because of #7783.
*
* @readonly
* @property {Boolean}
*/
synAnchorSelector: CKEDITOR.env.ie,
* For browsers that don't support CSS3 `a[name]:empty()`, note IE9 is included because of #7783.
*
* @readonly
* @deprecated 4.3.3 It is set to `false` on every browser.
* @property {Boolean} synAnchorSelector
*/

/**
* For browsers that have editing issue with empty anchor.
*
* @readonly
* @property {Boolean}
*/
emptyAnchorFix: CKEDITOR.env.ie && CKEDITOR.env.version < 8,
* For browsers that have editing issue with empty anchor.
*
* @readonly
* @deprecated 4.3.3 It is set to `false` on every browser.
* @property {Boolean} emptyAnchorFix
*/

/**
* @param {CKEDITOR.editor} editor
@@ -384,7 +340,7 @@ CKEDITOR.removeAnchorCommand.prototype = {
var sel = editor.getSelection(),
bms = sel.createBookmarks(),
anchor;
if ( sel && ( anchor = sel.getSelectedElement() ) && ( CKEDITOR.plugins.link.fakeAnchor && !anchor.getChildCount() ? CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, anchor ) : anchor.is( 'a' ) ) )
if ( sel && ( anchor = sel.getSelectedElement() ) && ( !anchor.getChildCount() ? CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, anchor ) : anchor.is( 'a' ) ) )
anchor.remove( 1 );
else {
if ( ( anchor = CKEDITOR.plugins.link.getSelectedLink( editor ) ) ) {

0 comments on commit 5875583

Please sign in to comment.
You can’t perform that action at this time.