Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F1107643
plugin.js
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
Sat, Aug 23, 9:02 AM
Size
22 KB
Mime Type
text/plain
Expires
Mon, Aug 25, 9:02 AM (1 h, 37 m)
Engine
blob
Format
Raw Data
Handle
715254
Attached To
rINP In-Portal
plugin.js
View Options
(
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
=
$internal_page_mapping
[
$page_id
];
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
;
}
}
$tmp_iframe
.
attr
(
'src'
,
$internal_page_mapping
[
$page_id
]);
}
// 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&admin=1'
);
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'
);
}
// Browser need the "href" fro copy/paste link to work. (#6641)
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
)
{
// 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
);
}
// 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
);
}
else
{
// We're only editing an existing link, so just overwrite the attributes.
var
element
=
this
.
_
.
selectedElement
,
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
);
selection
=
editor
.
getSelection
();
element
.
copyAttributes
(
newElement
,
{
name
:
1
}
);
element
.
moveChildren
(
newElement
);
newElement
.
replace
(
element
);
element
=
newElement
;
selection
.
selectElement
(
element
);
}
element
.
setAttributes
(
attributes
);
element
.
removeAttributes
(
removeAttributes
);
// Update text view when user changes protocol (#4612).
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'
]
);
}
// 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
);
delete
this
.
_
.
selectedElement
;
}
};
}
}
);
}
)();
Event Timeline
Log In to Comment