Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F726522
in-portal
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, Jan 5, 7:26 PM
Size
25 KB
Mime Type
text/x-diff
Expires
Tue, Jan 7, 7:26 PM (18 h, 9 m ago)
Engine
blob
Format
Raw Data
Handle
536636
Attached To
rINP In-Portal
in-portal
View Options
Index: branches/5.2.x/core/ckeditor/plugins/my_link/plugin.js
===================================================================
--- branches/5.2.x/core/ckeditor/plugins/my_link/plugin.js (revision 16480)
+++ branches/5.2.x/core/ckeditor/plugins/my_link/plugin.js (revision 16481)
@@ -1,706 +1,682 @@
(
function() {
CKEDITOR.plugins.add('my_link');
CKEDITOR.on(
'dialogDefinition',
function(ev) {
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
var editor = this;
if (dialogName == 'link') {
var plugin = CKEDITOR.plugins.link;
var $internal_page_mapping = {}; // mapping between @@PAGE_ID@@ and real url (for anchor loading)
var load_page_anchors = function ($page_id, dialog) {
var $url;
var $tmp_iframe = $('#tmp_iframe');
var $internal_page_anchors = dialog.getContentElement( 'info', 'internalPageAnchors' );
var $current_anchor = $('#' + $internal_page_anchors.domId).data('anchor');
$internal_page_anchors.clear();
$internal_page_anchors.add( 'Loading ...', '' );
if ( $tmp_iframe.length == 0 ) {
$tmp_iframe = $('<iframe width="0" height="0" id="tmp_iframe"></iframe>').appendTo('body');
$tmp_iframe.get(0).onload = function () {
var $anchors = $('a[name]', $tmp_iframe.get(0).contentWindow.document);
$internal_page_anchors.allowOnChange = false;
$internal_page_anchors.clear();
$internal_page_anchors.add( $anchors.length > 0 ? '' : '(No anchors available in the document)', '' );
$anchors.each(
function () {
$internal_page_anchors.add( $(this).attr('name') );
}
);
$internal_page_anchors.setValue($current_anchor);
$internal_page_anchors.allowOnChange = true;
}
}
$url = $internal_page_mapping[$page_id];
$url += ($url.indexOf('?') ? '&' : '?') + 'skip_last_template=1';
$tmp_iframe.attr('src', $url);
}
// Handles the event when the "Type" selection box is changed.
var linkTypeChanged = function()
{
var dialog = this.getDialog(),
partIds = [ 'internalOptions', 'urlOptions', 'anchorOptions', 'emailOptions' ],
typeValue = this.getValue(),
uploadTab = dialog.definition.getContents( 'upload' ),
uploadInitiallyHidden = uploadTab && uploadTab.hidden;
switch ( typeValue ) {
case 'url':
if ( editor.config.linkShowTargetTab )
dialog.showPage( 'target' );
if ( !uploadInitiallyHidden )
dialog.showPage( 'upload' );
break;
case 'internal':
if ( editor.config.linkShowTargetTab )
dialog.showPage( 'target' );
if ( !uploadInitiallyHidden )
dialog.hidePage( 'upload' );
// select internal page according to link url (on link type change)
var $url = dialog.getContentElement('info', 'url').getValue();
if ( $internal_page_mapping[$url] !== undefined ) {
dialog.getContentElement('info', 'internal_page').setValue($url);
}
break;
default:
dialog.hidePage( 'target' );
if ( !uploadInitiallyHidden )
dialog.hidePage( 'upload' );
break;
}
for ( var i = 0 ; i < partIds.length ; i++ )
{
var element = dialog.getContentElement( 'info', partIds[i] );
if ( !element )
continue;
element = element.getElement().getParent().getParent();
if ( partIds[i] == typeValue + 'Options' )
element.show();
else
element.hide();
}
dialog.layout();
};
var javascriptProtocolRegex = /^javascript:/,
emailRegex = /^mailto:([^?]+)(?:\?(.+))?$/,
emailSubjectRegex = /subject=([^;?:@&=$,\/]*)/,
emailBodyRegex = /body=([^;?:@&=$,\/]*)/,
anchorRegex = /^#(.*)$/,
urlRegex = /^((?:http|https|ftp|news):\/\/)?(.*)$/,
selectableTargets = /^(_(?:self|top|parent|blank))$/,
encodedEmailLinkRegex = /^javascript:void\(location\.href='mailto:'\+String\.fromCharCode\(([^)]+)\)(?:\+'(.*)')?\)$/,
functionCallProtectedEmailLinkRegex = /^javascript:([^(]+)\(([^)]+)\)$/,
internalPageRegex = /^@@[\d]+@@(#.*$|$)/; // CUSTOM
var popupRegex =
/\s*window.open\(\s*this\.href\s*,\s*(?:'([^']*)'|null)\s*,\s*'([^']*)'\s*\)\s*;\s*return\s*false;*\s*/;
var popupFeaturesRegex = /(?:^|,)([^=]+)=(\d+|yes|no)/gi;
var parseLink = function( editor, element )
{
var href = ( element && ( element.data( 'cke-saved-href' ) || element.getAttribute( 'href' ) ) ) || '',
javascriptMatch,
emailMatch,
anchorMatch,
urlMatch,
retval = {};
if ( ( javascriptMatch = href.match( javascriptProtocolRegex ) ) )
{
var emailProtection = editor.config.emailProtection || '';
if ( emailProtection == 'encode' )
{
href = href.replace( encodedEmailLinkRegex,
function ( match, protectedAddress, rest )
{
return 'mailto:' +
String.fromCharCode.apply( String, protectedAddress.split( ',' ) ) +
( rest && unescapeSingleQuote( rest ) );
});
}
// Protected email link as function call.
else if ( emailProtection )
{
href.replace( functionCallProtectedEmailLinkRegex, function( match, funcName, funcArgs )
{
if ( funcName == compiledProtectionFunction.name )
{
retval.type = 'email';
var email = retval.email = {};
var paramRegex = /[^,\s]+/g,
paramQuoteRegex = /(^')|('$)/g,
paramsMatch = funcArgs.match( paramRegex ),
paramsMatchLength = paramsMatch.length,
paramName,
paramVal;
for ( var i = 0; i < paramsMatchLength; i++ )
{
paramVal = decodeURIComponent( unescapeSingleQuote( paramsMatch[ i ].replace( paramQuoteRegex, '' ) ) );
paramName = compiledProtectionFunction.params[ i ].toLowerCase();
email[ paramName ] = paramVal;
}
email.address = [ email.name, email.domain ].join( '@' );
}
} );
}
}
if ( !retval.type )
{
if ( ( anchorMatch = href.match( anchorRegex ) ) )
{
retval.type = 'anchor';
retval.anchor = {};
retval.anchor.name = retval.anchor.id = anchorMatch[1];
}
// Protected email link as encoded string.
else if ( ( emailMatch = href.match( emailRegex ) ) )
{
var subjectMatch = href.match( emailSubjectRegex ),
bodyMatch = href.match( emailBodyRegex );
retval.type = 'email';
var email = ( retval.email = {} );
email.address = emailMatch[ 1 ];
subjectMatch && ( email.subject = decodeURIComponent( subjectMatch[ 1 ] ) );
bodyMatch && ( email.body = decodeURIComponent( bodyMatch[ 1 ] ) );
}
// CUSTOM: begin
else if ( href && href.match( internalPageRegex ) )
{
retval.type = 'internal';
retval.url = {};
retval.url.protocol = '';
retval.anchor = {};
if ( href.match(/^(.*)#(.*)$/) ) {
retval.url.url = RegExp.$1;
retval.internal_anchor = RegExp.$2;
}
else {
retval.url.url = href;
retval.internal_anchor = '';
}
}
// CUSTOM: end
// urlRegex matches empty strings, so need to check for href as well.
else if ( href && ( urlMatch = href.match( urlRegex ) ) )
{
retval.type = 'url';
retval.url = {};
retval.url.protocol = urlMatch[1];
retval.url.url = urlMatch[2];
}
// CUSTOM: begin
else {
retval.type = 'internal';
retval.url = {};
retval.url.protocol = '';
retval.url.url = '';
retval.internal_anchor = '';
}
// CUSTOM: end
}
// Load target and popup settings.
if ( element )
{
var target = element.getAttribute( 'target' );
retval.target = {};
retval.adv = {};
// IE BUG: target attribute is an empty string instead of null in IE if it's not set.
if ( !target )
{
var onclick = element.data( 'cke-pa-onclick' ) || element.getAttribute( 'onclick' ),
onclickMatch = onclick && onclick.match( popupRegex );
if ( onclickMatch )
{
retval.target.type = 'popup';
retval.target.name = onclickMatch[1];
var featureMatch;
while ( ( featureMatch = popupFeaturesRegex.exec( onclickMatch[2] ) ) )
{
// Some values should remain numbers (#7300)
if ( ( featureMatch[2] == 'yes' || featureMatch[2] == '1' ) && !( featureMatch[1] in { height:1, width:1, top:1, left:1 } ) )
retval.target[ featureMatch[1] ] = true;
else if ( isFinite( featureMatch[2] ) )
retval.target[ featureMatch[1] ] = featureMatch[2];
}
}
}
else
{
var targetMatch = target.match( selectableTargets );
if ( targetMatch )
retval.target.type = retval.target.name = target;
else
{
retval.target.type = 'frame';
retval.target.name = target;
}
}
var me = this;
var advAttr = function( inputName, attrName )
{
var value = element.getAttribute( attrName );
if ( value !== null )
retval.adv[ inputName ] = value || '';
};
advAttr( 'advId', 'id' );
advAttr( 'advLangDir', 'dir' );
advAttr( 'advAccessKey', 'accessKey' );
retval.adv.advName =
element.data( 'cke-saved-name' )
|| element.getAttribute( 'name' )
|| '';
advAttr( 'advLangCode', 'lang' );
advAttr( 'advTabIndex', 'tabindex' );
advAttr( 'advTitle', 'title' );
advAttr( 'advContentType', 'type' );
advAttr( 'advCSSClasses', 'class' );
advAttr( 'advCharset', 'charset' );
advAttr( 'advStyles', 'style' );
advAttr( 'advRel', 'rel' );
}
// Find out whether we have any anchors in the editor.
// Get all IMG elements in CK document.
var elements = editor.document.getElementsByTag( 'img' ),
realAnchors = new CKEDITOR.dom.nodeList( editor.document.$.anchors ),
anchors = retval.anchors = [];
for ( var i = 0; i < elements.count() ; i++ )
{
var item = elements.getItem( i );
if ( item.data( 'cke-realelement' ) && item.data( 'cke-real-element-type' ) == 'anchor' )
anchors.push( editor.restoreRealElement( item ) );
}
for ( i = 0 ; i < realAnchors.count() ; i++ )
anchors.push( realAnchors.getItem( i ) );
for ( i = 0 ; i < anchors.length ; i++ )
{
item = anchors[ i ];
anchors[ i ] = { name : item.getAttribute( 'name' ), id : item.getAttribute( 'id' ) };
}
// Record down the selected element in the dialog.
this._.selectedElement = element;
return retval;
};
var infoTab = dialogDefinition.getContents( 'info' );
var linkType = infoTab.get('linkType');
linkType['items'].unshift( ['Internal Web Page', 'internal'] );
linkType['default'] = 'internal';
linkType['onChange'] = linkTypeChanged;
infoTab.add(
{
type : 'vbox',
id : 'internalOptions',
children :
[
{
type : 'select',
id : 'internal_page',
label : 'Internal Page Name',
items : [
[ '' ]
],
onChange: function ( ) {
// place internal page ID from this dropdown into URL field of the dialog
var dialog = this.getDialog();
this.allowOnChange = false;
dialog.getContentElement('info', 'url').setValue( this.getValue() );
this.allowOnChange = true;
load_page_anchors( this.getValue(), dialog );
},
setup : function( data ) {
var $me = this;
var $link_url = data.url ? data.url.url : '';
var $ajax_url = CKEDITOR.basePath.replace( /core.*$/, 'admin/index.php?events[fck]=OnLoadCmsTree' );
var $internal_page_anchors = this.getDialog().getContentElement( 'info', 'internalPageAnchors' );
$('#' + $internal_page_anchors.domId).data('anchor', data.internal_anchor);
$.ajax(
{
type: 'GET',
url: $ajax_url,
async: false,
success: function ($xml) {
$me.allowOnChange = false;
$me.clear();
$me.add( '' );
$('CmsPage', $xml).each(
function ($i) {
var $node = $(this);
var cms_id = $node.attr('st_id');
var cms_page = $node.attr('path');
var real_url = $node.attr('real_url');
$internal_page_mapping[cms_page] = real_url;
$me.add( $node.attr('title').replace(/&/g, '&') , cms_page );
if ( $link_url && $link_url.match(cms_page + '$') ) {
$me.setValue(cms_page);
load_page_anchors( cms_page, $me.getDialog() );
}
}
);
// undo CKEditor default "htmlspecialchars" on all HTML
$('option', '#' + $me.domId).each(
function ($index) {
var $option = $(this),
$level_indicator = '—',
$html = $option.html().replace(/&/g, '&'),
$level = ($html.length - $html.replace(new RegExp($level_indicator, 'g'), '').length ) / $level_indicator.length;
if ( $html.match(/^(.*?) (.*?) (\(.*?\))$/) ) {
// "—— rss (news/rss.html)"
$level_indicator = RegExp.$1;
var $page_name = RegExp.$2,
$page_url = RegExp.$3;
$html = $level_indicator + ' ' + $page_name + ' ' + $page_url;
}
$option.html($html);
}
);
$me.allowOnChange = true;
$me.getDialog().layout();
},
dataType: 'xml'
}
);
var linkType = this.getDialog().getContentElement( 'info', 'linkType' );
if ( linkType && linkType.getValue() == 'internal' ) {
this.focus();
}
},
},
{
type : 'select',
id : 'internalPageAnchors',
label : 'Select an Anchor',
items : [
[ '' ]
],
commit : function( data ) {
data.internal_anchor = this.getValue();
this.allowOnChange = false;
}
}
]
}
);
dialogDefinition['onShow'] = function() {
this.fakeObj = false;
var editor = this.getParentEditor(),
selection = editor.getSelection(),
element = null;
// Fill in all the relevant fields if there's already one link selected.
if ( ( element = plugin.getSelectedLink( editor ) ) && element.hasAttribute( 'href' ) )
selection.selectElement( element );
else if ( ( element = selection.getSelectedElement() ) && element.is( 'img' )
&& element.data( 'cke-real-element-type' )
&& element.data( 'cke-real-element-type' ) == 'anchor' )
{
this.fakeObj = element;
element = editor.restoreRealElement( this.fakeObj );
selection.selectElement( this.fakeObj );
}
else
element = null;
this.setupContent( parseLink.apply( this, [ editor, element ] ) );
};
dialogDefinition['onOk'] = function() {
var attributes = {},
removeAttributes = [],
data = {},
me = this,
editor = this.getParentEditor();
this.commitContent( data );
// Compose the URL.
switch ( data.type || 'internal' )
{
// CUSTOM: begin
case 'internal':
var url = ( data.url && data.url.url ) || '';
var anchor = data.internal_anchor || '';
attributes[ 'data-cke-saved-href' ] = url;
if ( anchor ) {
attributes[ 'data-cke-saved-href' ] += '#' + anchor;
}
break;
// CUSTOM: end
case 'url':
var protocol = ( data.url && data.url.protocol != undefined ) ? data.url.protocol : 'http://',
url = ( data.url && data.url.url ) || '';
attributes[ 'data-cke-saved-href' ] = ( url.indexOf( '/' ) === 0 ) ? url : protocol + url;
break;
case 'anchor':
var name = ( data.anchor && data.anchor.name ),
id = ( data.anchor && data.anchor.id );
attributes[ 'data-cke-saved-href' ] = '#' + ( name || id || '' );
break;
case 'email':
var linkHref,
email = data.email,
address = email.address,
emailProtection = editor.config.emailProtection || '';
switch( emailProtection )
{
case '' :
case 'encode' :
{
var subject = encodeURIComponent( email.subject || '' ),
body = encodeURIComponent( email.body || '' );
// Build the e-mail parameters first.
var argList = [];
subject && argList.push( 'subject=' + subject );
body && argList.push( 'body=' + body );
argList = argList.length ? '?' + argList.join( '&' ) : '';
if ( emailProtection == 'encode' )
{
linkHref = [ 'javascript:void(location.href=\'mailto:\'+',
protectEmailAddressAsEncodedString( address ) ];
// parameters are optional.
argList && linkHref.push( '+\'', escapeSingleQuote( argList ), '\'' );
linkHref.push( ')' );
}
else
linkHref = [ 'mailto:', address, argList ];
break;
}
default :
{
// Separating name and domain.
var nameAndDomain = address.split( '@', 2 );
email.name = nameAndDomain[ 0 ];
email.domain = nameAndDomain[ 1 ];
linkHref = [ 'javascript:', protectEmailLinkAsFunction( email ) ];
}
}
attributes[ 'data-cke-saved-href' ] = linkHref.join( '' );
break;
}
// Popups and target.
if ( data.target )
{
if ( data.target.type == 'popup' )
{
var onclickList = [ 'window.open(this.href, \'',
data.target.name || '', '\', \'' ];
var featureList = [ 'resizable', 'status', 'location', 'toolbar', 'menubar', 'fullscreen',
'scrollbars', 'dependent' ];
var featureLength = featureList.length;
var addFeature = function( featureName )
{
if ( data.target[ featureName ] )
featureList.push( featureName + '=' + data.target[ featureName ] );
};
for ( var i = 0 ; i < featureLength ; i++ )
featureList[i] = featureList[i] + ( data.target[ featureList[i] ] ? '=yes' : '=no' ) ;
addFeature( 'width' );
addFeature( 'left' );
addFeature( 'height' );
addFeature( 'top' );
onclickList.push( featureList.join( ',' ), '\'); return false;' );
attributes[ 'data-cke-pa-onclick' ] = onclickList.join( '' );
// Add the "target" attribute. (#5074)
removeAttributes.push( 'target' );
}
else
{
if ( data.target.type != 'notSet' && data.target.name )
attributes.target = data.target.name;
else
removeAttributes.push( 'target' );
removeAttributes.push( 'data-cke-pa-onclick', 'onclick' );
}
}
// Advanced attributes.
if ( data.adv )
{
var advAttr = function( inputName, attrName )
{
var value = data.adv[ inputName ];
if ( value )
attributes[attrName] = value;
else
removeAttributes.push( attrName );
};
advAttr( 'advId', 'id' );
advAttr( 'advLangDir', 'dir' );
advAttr( 'advAccessKey', 'accessKey' );
if ( data.adv[ 'advName' ] )
{
attributes[ 'name' ] = attributes[ 'data-cke-saved-name' ] = data.adv[ 'advName' ];
attributes[ 'class' ] = ( attributes[ 'class' ] ? attributes[ 'class' ] + ' ' : '' ) + 'cke_anchor';
}
else
removeAttributes = removeAttributes.concat( [ 'data-cke-saved-name', 'name' ] );
advAttr( 'advLangCode', 'lang' );
advAttr( 'advTabIndex', 'tabindex' );
advAttr( 'advTitle', 'title' );
advAttr( 'advContentType', 'type' );
advAttr( 'advCSSClasses', 'class' );
advAttr( 'advCharset', 'charset' );
advAttr( 'advStyles', 'style' );
advAttr( 'advRel', 'rel' );
}
+ var selection = editor.getSelection();
// Browser need the "href" fro copy/paste link to work. (#6641)
- attributes.href = attributes[ 'data-cke-saved-href' ];
+ attributes.href = attributes['data-cke-saved-href'];
- if ( !this._.selectedElement )
- {
- // Create element if current selection is collapsed.
- var selection = editor.getSelection(),
- ranges = selection.getRanges( true );
- if ( ranges.length == 1 && ranges[0].collapsed )
- {
+ if ( !this._.selectedElement ) {
+ var range = selection.getRanges(1)[0];
+
+ // Use link URL as text with a collapsed cursor.
+ if ( range.collapsed ) {
// Short mailto link text view (#5736).
- var text = new CKEDITOR.dom.text( data.type == 'email' ?
- data.email.address : attributes[ 'data-cke-saved-href' ], editor.document );
- ranges[0].insertNode( text );
- ranges[0].selectNodeContents( text );
- selection.selectRanges( ranges );
+ var text = new CKEDITOR.dom.text(data.type == 'email' ? data.email.address : attributes['data-cke-saved-href'], editor.document);
+ range.insertNode(text);
+ range.selectNodeContents(text);
}
// Apply style.
- var style = new CKEDITOR.style( { element : 'a', attributes : attributes } );
- style.type = CKEDITOR.STYLE_INLINE; // need to override... dunno why.
- style.apply( editor.document );
+ var style = new CKEDITOR.style({element: 'a', attributes: attributes});
+ style.type = CKEDITOR.STYLE_INLINE; // need to override... dunno why.
+ style.applyToRange(range);
+ range.select();
}
- else
- {
+ else {
// We're only editing an existing link, so just overwrite the attributes.
var element = this._.selectedElement,
- href = element.data( 'cke-saved-href' ),
+ href = element.data('cke-saved-href'),
textView = element.getHtml();
- // IE BUG: Setting the name attribute to an existing link doesn't work.
- // Must re-create the link from weired syntax to workaround.
- if ( CKEDITOR.env.ie && !( CKEDITOR.document.$.documentMode >= 8 ) && attributes.name != element.getAttribute( 'name' ) )
- {
- var newElement = new CKEDITOR.dom.element( '<a name="' + CKEDITOR.tools.htmlEncode( attributes.name ) + '">',
- editor.document );
+ element.setAttributes(attributes);
+ element.removeAttributes(removeAttributes);
- selection = editor.getSelection();
-
- element.copyAttributes( newElement, { name : 1 } );
- element.moveChildren( newElement );
- newElement.replace( element );
- element = newElement;
-
- selection.selectElement( element );
+ if ( data.adv && data.adv.advName && CKEDITOR.plugins.link.synAnchorSelector ) {
+ element.addClass(element.getChildCount() ? 'cke_anchor' : 'cke_anchor_empty');
}
- element.setAttributes( attributes );
- element.removeAttributes( removeAttributes );
// Update text view when user changes protocol (#4612).
- if ( href == textView || data.type == 'email' && textView.indexOf( '@' ) != -1 )
- {
+ if ( href == textView || data.type == 'email' && textView.indexOf('@') != -1 ) {
// Short mailto link text view (#5736).
- element.setHtml( data.type == 'email' ?
- data.email.address : attributes[ 'data-cke-saved-href' ] );
+ element.setHtml(data.type == 'email' ? data.email.address : attributes['data-cke-saved-href']);
}
- // Make the element display as an anchor if a name has been set.
- if ( element.getAttribute( 'name' ) )
- element.addClass( 'cke_anchor' );
- else
- element.removeClass( 'cke_anchor' );
-
- if ( this.fakeObj )
- editor.createFakeElement( element, 'cke_anchor', 'anchor' ).replace( this.fakeObj );
+ selection.selectElement(element);
delete this._.selectedElement;
}
};
}
}
);
}
)();
Event Timeline
Log In to Comment