app/assets/javascripts/ckeditor/plugins/adv_link/dialogs/link.js.coffee
###
@license Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.md or http://ckeditor.com/license
###
#
# Function to get current content locale
#
getParameterByName = (name, href) ->
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]")
regexS = "[\\?&]" + name + "=([^&#]*)"
regex = new RegExp(regexS)
results = regex.exec(href)
unless results?
""
else
decodeURIComponent results[1].replace(/\+/g, " ")
CKEDITOR.dialog.add "link", (editor) ->
unescapeSingleQuote = (str) ->
str.replace /\\'/g, "'"
escapeSingleQuote = (str) ->
str.replace /'/g, "\\$&"
# Compile the protection function pattern.
protectEmailLinkAsFunction = (email) ->
retval = undefined
name = compiledProtectionFunction.name
params = compiledProtectionFunction.params
paramName = undefined
paramValue = undefined
retval = [
name
"("
]
i = 0
while i < params.length
paramName = params[i].toLowerCase()
paramValue = email[paramName]
i > 0 and retval.push(",")
retval.push "'", (if paramValue then escapeSingleQuote(encodeURIComponent(email[paramName])) else ""), "'"
i++
retval.push ")"
retval.join ""
protectEmailAddressAsEncodedString = (address) ->
charCode = undefined
length = address.length
encodedChars = []
i = 0
while i < length
charCode = address.charCodeAt(i)
encodedChars.push charCode
i++
"String.fromCharCode(" + encodedChars.join(",") + ")"
getLinkClass = (ele) ->
className = ele.getAttribute("class")
(if className then className.replace(/\s*(?:cke_anchor_empty|cke_anchor)(?:\s*$)?/g, "") else "")
plugin = CKEDITOR.plugins.link
targetChanged = ->
dialog = @getDialog()
popupFeatures = dialog.getContentElement("target", "popupFeatures")
targetName = dialog.getContentElement("target", "linkTargetName")
value = @getValue()
return if not popupFeatures or not targetName
popupFeatures = popupFeatures.getElement()
popupFeatures.hide()
targetName.setValue ""
switch value
when "frame"
targetName.setLabel editor.lang.link.targetFrameName
targetName.getElement().show()
when "popup"
popupFeatures.show()
targetName.setLabel editor.lang.link.targetPopupName
targetName.getElement().show()
else
targetName.setValue value
targetName.getElement().hide()
# Handles the event when the "Target" selection box is changed.
linkTypeChanged = ->
dialog = @getDialog()
partIds = [
"urlOptions"
"localPageOptions"
"anchorOptions"
"emailOptions"
]
typeValue = @getValue()
uploadTab = dialog.definition.getContents("upload")
uploadInitiallyHidden = uploadTab and uploadTab.hidden
if typeValue is "url"
dialog.showPage "target" if editor.config.linkShowTargetTab
dialog.showPage "upload" unless uploadInitiallyHidden
else
dialog.hidePage "target"
dialog.hidePage "upload" unless uploadInitiallyHidden
i = 0
while i < partIds.length
element = dialog.getContentElement("info", partIds[i])
continue unless element
element = element.getElement().getParent().getParent()
if partIds[i] is typeValue + "Options"
element.show()
else
element.hide()
i++
dialog.layout()
return
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:([^(]+)\(([^)]+)\)$/
popupRegex = /\s*window.open\(\s*this\.href\s*,\s*(?:'([^']*)'|null)\s*,\s*'([^']*)'\s*\)\s*;\s*return\s*false;*\s*/
popupFeaturesRegex = /(?:^|,)([^=]+)=(\d+|yes|no)/g
parseLink = (editor, element) ->
href = (element and (element.data("cke-saved-href") or element.getAttribute("href"))) or ""
javascriptMatch = undefined
emailMatch = undefined
anchorMatch = undefined
urlMatch = undefined
retval = {}
if javascriptMatch = href.match(javascriptProtocolRegex)
if emailProtection is "encode"
href = href.replace(encodedEmailLinkRegex, (match, protectedAddress, rest) ->
"mailto:" + String.fromCharCode.apply(String, protectedAddress.split(",")) + (rest and unescapeSingleQuote(rest))
)
else if emailProtection
href.replace functionCallProtectedEmailLinkRegex, (match, funcName, funcArgs) ->
if funcName is compiledProtectionFunction.name
retval.type = "email"
email = retval.email = {}
paramRegex = /[^,\s]+/g
paramQuoteRegex = /(^')|('$)/g
paramsMatch = funcArgs.match(paramRegex)
paramsMatchLength = paramsMatch.length
paramName = undefined
paramVal = undefined
i = 0
while i < paramsMatchLength
paramVal = decodeURIComponent(unescapeSingleQuote(paramsMatch[i].replace(paramQuoteRegex, "")))
paramName = compiledProtectionFunction.params[i].toLowerCase()
email[paramName] = paramVal
i++
email.address = [
email.name
email.domain
].join("@")
return
unless retval.type
if anchorMatch = href.match(anchorRegex)
retval.type = "anchor"
retval.anchor = {}
retval.anchor.name = retval.anchor.id = anchorMatch[1]
else if emailMatch = href.match(emailRegex)
subjectMatch = href.match(emailSubjectRegex)
bodyMatch = href.match(emailBodyRegex)
retval.type = "email"
email = (retval.email = {})
email.address = emailMatch[1]
subjectMatch and (email.subject = decodeURIComponent(subjectMatch[1]))
bodyMatch and (email.body = decodeURIComponent(bodyMatch[1]))
else if href and (urlMatch = href.match(urlRegex))
retval.type = "url"
retval.url = {}
retval.url.protocol = urlMatch[1]
retval.url.url = urlMatch[2]
else
retval.type = "url"
if element
target = element.getAttribute("target")
retval.target = {}
retval.adv = {}
unless target
onclick = element.data("cke-pa-onclick") or element.getAttribute("onclick")
onclickMatch = onclick and onclick.match(popupRegex)
if onclickMatch
retval.target.type = "popup"
retval.target.name = onclickMatch[1]
featureMatch = undefined
while (featureMatch = popupFeaturesRegex.exec(onclickMatch[2]))
if (featureMatch[2] is "yes" or featureMatch[2] is "1") and (featureMatch[1] of
height: 1
width: 1
top: 1
left: 1
)
retval.target[featureMatch[1]] = true
else retval.target[featureMatch[1]] = featureMatch[2] if isFinite(featureMatch[2])
else
targetMatch = target.match(selectableTargets)
if targetMatch
retval.target.type = retval.target.name = target
else
retval.target.type = "frame"
retval.target.name = target
me = this
advAttr = (inputName, attrName) ->
value = element.getAttribute(attrName)
retval.adv[inputName] = value or "" if value isnt null
return
advAttr "advId", "id"
advAttr "advLangDir", "dir"
advAttr "advAccessKey", "accessKey"
retval.adv.advName = element.data("cke-saved-name") or element.getAttribute("name") or ""
advAttr "advLangCode", "lang"
advAttr "advTabIndex", "tabindex"
advAttr "advTitle", "title"
advAttr "advContentType", "type"
(if CKEDITOR.plugins.link.synAnchorSelector then retval.adv.advCSSClasses = getLinkClass(element) else advAttr("advCSSClasses", "class"))
advAttr "advCharset", "charset"
advAttr "advStyles", "style"
advAttr "advRel", "rel"
anchors = retval.anchors = []
i = undefined
count = undefined
item = undefined
if CKEDITOR.plugins.link.emptyAnchorFix
links = editor.document.getElementsByTag("a")
i = 0
count = links.count()
while i < count
item = links.getItem(i)
if item.data("cke-saved-name") or item.hasAttribute("name")
anchors.push
name: item.data("cke-saved-name") or item.getAttribute("name")
id: item.getAttribute("id")
i++
else
anchorList = new CKEDITOR.dom.nodeList(editor.document.$.anchors)
i = 0
count = anchorList.count()
while i < count
item = anchorList.getItem(i)
anchors[i] =
name: item.getAttribute("name")
id: item.getAttribute("id")
i++
if CKEDITOR.plugins.link.fakeAnchor
imgs = editor.document.getElementsByTag("img")
i = 0
count = imgs.count()
while i < count
if item = CKEDITOR.plugins.link.tryRestoreFakeAnchor(editor, imgs.getItem(i))
anchors.push
name: item.getAttribute("name")
id: item.getAttribute("id")
i++
@_.selectedElement = element
retval
setupParams = (page, data) ->
@setValue data[page][@id] or "" if data[page]
return
setupPopupParams = (data) ->
setupParams.call this, "target", data
setupAdvParams = (data) ->
setupParams.call this, "adv", data
commitParams = (page, data) ->
data[page] = {} unless data[page]
data[page][@id] = @getValue() or ""
return
commitPopupParams = (data) ->
commitParams.call this, "target", data
commitAdvParams = (data) ->
commitParams.call this, "adv", data
emailProtection = editor.config.emailProtection or ""
if emailProtection and emailProtection isnt "encode"
compiledProtectionFunction = {}
emailProtection.replace /^([^(]+)\(([^)]+)\)$/, (match, funcName, params) ->
compiledProtectionFunction.name = funcName
compiledProtectionFunction.params = []
params.replace /[^,\s]+/g, (param) ->
compiledProtectionFunction.params.push param
return
return
commonLang = editor.lang.common
linkLang = editor.lang.adv_link # modified by simo
title: linkLang.title
minWidth: 350
minHeight: 230
contents: [
{
id: "info"
label: linkLang.info
title: linkLang.info
elements: [
{
id: "linkType"
type: "select"
label: linkLang.type
default: "url"
items: [
[
linkLang.toUrl
"url"
]
[ # added by @simo - http://blog.xoundboy.com/?p=393
linkLang.localPages
"localPage"
]
[
linkLang.toAnchor
"anchor"
]
[
linkLang.toEmail
"email"
]
]
onChange: linkTypeChanged
setup: (data) ->
@setValue data.type if data.type
return
commit: (data) ->
data.type = @getValue()
return
}
{
# added by @simo - http://blog.xoundboy.com/?p=393
# see also : http://docs.ckeditor.com/source/dialogDefinition.html#CKEDITOR-dialog-definition-uiElement-property-type
# http://docs.ckeditor.com/#!/guide/plugin_sdk_sample_1
type: "vbox"
id: "localPageOptions"
children: [
type: "select"
label: linkLang.selectPageLabel
id: "localPage"
title: linkLang.selectPageTitle
# items: eval(decodeURIComponent(document.getElementById("pageListJSON").value)),
items: []
onLoad: (element) ->
element_id = "#" + @getInputElement().$.id
# ajax call indpired from http://stackoverflow.com/questions/5293920/ckeditor-dynamic-select-in-a-dialog
$.ajax
type: "GET"
#contentType: 'application/json; charset=utf-8',
url: "/" + getParameterByName("content_locale", document.location.href) + "/api/pages.json"
dataType: "json"
async: false
success: (data) ->
$.each data, (index, item) ->
$(element_id).get(0).options[$(element_id).get(0).options.length] = new Option(decodeURIComponent(item.title) + ': ' + item.pretty_url, item.url)
return
return
error: (xhr, ajaxOptions, thrownError) ->
alert xhr.status
alert thrownError
return
return
commit: (data) ->
data.localPage = {} unless data.localPage
data.localPage = @getValue()
return
]
}
{
# added by @simo - end
type: "vbox"
id: "urlOptions"
children: [
{
type: "hbox"
widths: [
"25%"
"75%"
]
children: [
{
id: "protocol"
type: "select"
label: commonLang.protocol
default: "http://"
items: [
# Force 'ltr' for protocol names in BIDI. (#5433)
[
"http://"
"http://"
]
[
"https://"
"https://"
]
[
"ftp://"
"ftp://"
]
[
"news://"
"news://"
]
[
linkLang.other
""
]
]
setup: (data) ->
@setValue data.url.protocol or "" if data.url
return
commit: (data) ->
data.url = {} unless data.url
data.url.protocol = @getValue()
return
}
{
type: "text"
id: "url"
label: commonLang.url
required: true
onLoad: ->
@allowOnChange = true
return
onKeyUp: ->
@allowOnChange = false
protocolCmb = @getDialog().getContentElement("info", "protocol")
url = @getValue()
urlOnChangeProtocol = /^(http|https|ftp|news):\/\/(?=.)/i
urlOnChangeTestOther = /^((javascript:)|[#\/\.\?])/i
protocol = urlOnChangeProtocol.exec(url)
if protocol
@setValue url.substr(protocol[0].length)
protocolCmb.setValue protocol[0].toLowerCase()
else protocolCmb.setValue "" if urlOnChangeTestOther.test(url)
@allowOnChange = true
return
onChange: ->
# Dont't call on dialog load.
@onKeyUp() if @allowOnChange
return
validate: ->
dialog = @getDialog()
return true if dialog.getContentElement("info", "linkType") and dialog.getValueOf("info", "linkType") isnt "url"
if (/javascript\:/).test(@getValue())
alert commonLang.invalidValue
return false
# Edit Anchor.
return true if @getDialog().fakeObj
func = CKEDITOR.dialog.validate.notEmpty(linkLang.noUrl)
func.apply this
setup: (data) ->
@allowOnChange = false
@setValue data.url.url if data.url
@allowOnChange = true
return
commit: (data) ->
# IE will not trigger the onChange event if the mouse has been used
# to carry all the operations #4724
@onChange()
data.url = {} unless data.url
data.url.url = @getValue()
@allowOnChange = false
return
}
]
setup: (data) ->
@getElement().show() unless @getDialog().getContentElement("info", "linkType")
return
}
{
type: "button"
id: "browse"
hidden: "true"
filebrowser: "info:url"
label: commonLang.browseServer
}
]
}
{
type: "vbox"
id: "anchorOptions"
width: 260
align: "center"
padding: 0
children: [
{
type: "fieldset"
id: "selectAnchorText"
label: linkLang.selectAnchor
setup: (data) ->
if data.anchors.length > 0
@getElement().show()
else
@getElement().hide()
return
children: [
type: "hbox"
id: "selectAnchor"
children: [
{
type: "select"
id: "anchorName"
default: ""
label: linkLang.anchorName
style: "width: 100%;"
items: [[""]]
setup: (data) ->
@clear()
@add ""
i = 0
while i < data.anchors.length
@add data.anchors[i].name if data.anchors[i].name
i++
@setValue data.anchor.name if data.anchor
linkType = @getDialog().getContentElement("info", "linkType")
@focus() if linkType and linkType.getValue() is "email"
return
commit: (data) ->
data.anchor = {} unless data.anchor
data.anchor.name = @getValue()
return
}
{
type: "select"
id: "anchorId"
default: ""
label: linkLang.anchorId
style: "width: 100%;"
items: [[""]]
setup: (data) ->
@clear()
@add ""
i = 0
while i < data.anchors.length
@add data.anchors[i].id if data.anchors[i].id
i++
@setValue data.anchor.id if data.anchor
return
commit: (data) ->
data.anchor = {} unless data.anchor
data.anchor.id = @getValue()
return
}
]
setup: (data) ->
if data.anchors.length > 0
@getElement().show()
else
@getElement().hide()
return
]
}
{
type: "html"
id: "noAnchors"
style: "text-align: center;"
html: "<div role=\"note\" tabIndex=\"-1\">" + CKEDITOR.tools.htmlEncode(linkLang.noAnchors) + "</div>"
# Focus the first element defined in above html.
focus: true
setup: (data) ->
if data.anchors.length < 1
@getElement().show()
else
@getElement().hide()
return
}
]
setup: (data) ->
@getElement().hide() unless @getDialog().getContentElement("info", "linkType")
return
}
{
type: "vbox"
id: "emailOptions"
padding: 1
children: [
{
type: "text"
id: "emailAddress"
label: linkLang.emailAddress
required: true
validate: ->
dialog = @getDialog()
return true if not dialog.getContentElement("info", "linkType") or dialog.getValueOf("info", "linkType") isnt "email"
func = CKEDITOR.dialog.validate.notEmpty(linkLang.noEmail)
func.apply this
setup: (data) ->
@setValue data.email.address if data.email
linkType = @getDialog().getContentElement("info", "linkType")
@select() if linkType and linkType.getValue() is "email"
return
commit: (data) ->
data.email = {} unless data.email
data.email.address = @getValue()
return
}
{
type: "text"
id: "emailSubject"
label: linkLang.emailSubject
setup: (data) ->
@setValue data.email.subject if data.email
return
commit: (data) ->
data.email = {} unless data.email
data.email.subject = @getValue()
return
}
{
type: "textarea"
id: "emailBody"
label: linkLang.emailBody
rows: 3
default: ""
setup: (data) ->
@setValue data.email.body if data.email
return
commit: (data) ->
data.email = {} unless data.email
data.email.body = @getValue()
return
}
]
setup: (data) ->
@getElement().hide() unless @getDialog().getContentElement("info", "linkType")
return
}
]
}
{
id: "target"
requiredContent: "a[target]" # This is not fully correct, because some target option requires JS.
label: linkLang.target
title: linkLang.target
elements: [
{
type: "hbox"
widths: [
"50%"
"50%"
]
children: [
{
type: "select"
id: "linkTargetType"
label: commonLang.target
default: "notSet"
style: "width : 100%;"
items: [
[
commonLang.notSet
"notSet"
]
[
linkLang.targetFrame
"frame"
]
[
linkLang.targetPopup
"popup"
]
[
commonLang.targetNew
"_blank"
]
[
commonLang.targetTop
"_top"
]
[
commonLang.targetSelf
"_self"
]
[
commonLang.targetParent
"_parent"
]
]
onChange: targetChanged
setup: (data) ->
@setValue data.target.type or "notSet" if data.target
targetChanged.call this
return
commit: (data) ->
data.target = {} unless data.target
data.target.type = @getValue()
return
}
{
type: "text"
id: "linkTargetName"
label: linkLang.targetFrameName
default: ""
setup: (data) ->
@setValue data.target.name if data.target
return
commit: (data) ->
data.target = {} unless data.target
data.target.name = @getValue().replace(/\W/g, "")
return
}
]
}
{
type: "vbox"
width: "100%"
align: "center"
padding: 2
id: "popupFeatures"
children: [
type: "fieldset"
label: linkLang.popupFeatures
children: [
{
type: "hbox"
children: [
{
type: "checkbox"
id: "resizable"
label: linkLang.popupResizable
setup: setupPopupParams
commit: commitPopupParams
}
{
type: "checkbox"
id: "status"
label: linkLang.popupStatusBar
setup: setupPopupParams
commit: commitPopupParams
}
]
}
{
type: "hbox"
children: [
{
type: "checkbox"
id: "location"
label: linkLang.popupLocationBar
setup: setupPopupParams
commit: commitPopupParams
}
{
type: "checkbox"
id: "toolbar"
label: linkLang.popupToolbar
setup: setupPopupParams
commit: commitPopupParams
}
]
}
{
type: "hbox"
children: [
{
type: "checkbox"
id: "menubar"
label: linkLang.popupMenuBar
setup: setupPopupParams
commit: commitPopupParams
}
{
type: "checkbox"
id: "fullscreen"
label: linkLang.popupFullScreen
setup: setupPopupParams
commit: commitPopupParams
}
]
}
{
type: "hbox"
children: [
{
type: "checkbox"
id: "scrollbars"
label: linkLang.popupScrollBars
setup: setupPopupParams
commit: commitPopupParams
}
{
type: "checkbox"
id: "dependent"
label: linkLang.popupDependent
setup: setupPopupParams
commit: commitPopupParams
}
]
}
{
type: "hbox"
children: [
{
type: "text"
widths: [
"50%"
"50%"
]
labelLayout: "horizontal"
label: commonLang.width
id: "width"
setup: setupPopupParams
commit: commitPopupParams
}
{
type: "text"
labelLayout: "horizontal"
widths: [
"50%"
"50%"
]
label: linkLang.popupLeft
id: "left"
setup: setupPopupParams
commit: commitPopupParams
}
]
}
{
type: "hbox"
children: [
{
type: "text"
labelLayout: "horizontal"
widths: [
"50%"
"50%"
]
label: commonLang.height
id: "height"
setup: setupPopupParams
commit: commitPopupParams
}
{
type: "text"
labelLayout: "horizontal"
label: linkLang.popupTop
widths: [
"50%"
"50%"
]
id: "top"
setup: setupPopupParams
commit: commitPopupParams
}
]
}
]
]
}
]
}
{
id: "upload"
label: linkLang.upload
title: linkLang.upload
hidden: true
filebrowser: "uploadButton"
elements: [
{
type: "file"
id: "upload"
label: commonLang.upload
style: "height:40px"
size: 29
}
{
type: "fileButton"
id: "uploadButton"
label: commonLang.uploadSubmit
filebrowser: "info:url"
for: [
"upload"
"upload"
]
}
]
}
{
id: "advanced"
label: linkLang.advanced
title: linkLang.advanced
elements: [
{
type: "vbox"
padding: 1
children: [
{
type: "hbox"
widths: [
"45%"
"35%"
"20%"
]
children: [
{
type: "text"
id: "advId"
requiredContent: "a[id]"
label: linkLang.id
setup: setupAdvParams
commit: commitAdvParams
}
{
type: "select"
id: "advLangDir"
requiredContent: "a[dir]"
label: linkLang.langDir
default: ""
style: "width:110px"
items: [
[
commonLang.notSet
""
]
[
linkLang.langDirLTR
"ltr"
]
[
linkLang.langDirRTL
"rtl"
]
]
setup: setupAdvParams
commit: commitAdvParams
}
{
type: "text"
id: "advAccessKey"
requiredContent: "a[accesskey]"
width: "80px"
label: linkLang.acccessKey
maxLength: 1
setup: setupAdvParams
commit: commitAdvParams
}
]
}
{
type: "hbox"
widths: [
"45%"
"35%"
"20%"
]
children: [
{
type: "text"
label: linkLang.name
id: "advName"
requiredContent: "a[name]"
setup: setupAdvParams
commit: commitAdvParams
}
{
type: "text"
label: linkLang.langCode
id: "advLangCode"
requiredContent: "a[lang]"
width: "110px"
default: ""
setup: setupAdvParams
commit: commitAdvParams
}
{
type: "text"
label: linkLang.tabIndex
id: "advTabIndex"
requiredContent: "a[tabindex]"
width: "80px"
maxLength: 5
setup: setupAdvParams
commit: commitAdvParams
}
]
}
]
}
{
type: "vbox"
padding: 1
children: [
{
type: "hbox"
widths: [
"45%"
"55%"
]
children: [
{
type: "text"
label: linkLang.advisoryTitle
requiredContent: "a[title]"
default: ""
id: "advTitle"
setup: setupAdvParams
commit: commitAdvParams
}
{
type: "text"
label: linkLang.advisoryContentType
requiredContent: "a[type]"
default: ""
id: "advContentType"
setup: setupAdvParams
commit: commitAdvParams
}
]
}
{
type: "hbox"
widths: [
"45%"
"55%"
]
children: [
{
type: "text"
label: linkLang.cssClasses
requiredContent: "a(cke-xyz)" # Random text like 'xyz' will check if all are allowed.
default: ""
id: "advCSSClasses"
setup: setupAdvParams
commit: commitAdvParams
}
{
type: "text"
label: linkLang.charset
requiredContent: "a[charset]"
default: ""
id: "advCharset"
setup: setupAdvParams
commit: commitAdvParams
}
]
}
{
type: "hbox"
widths: [
"45%"
"55%"
]
children: [
{
type: "text"
label: linkLang.rel
requiredContent: "a[rel]"
default: ""
id: "advRel"
setup: setupAdvParams
commit: commitAdvParams
}
{
type: "text"
label: linkLang.styles
requiredContent: "a{cke-xyz}" # Random text like 'xyz' will check if all are allowed.
default: ""
id: "advStyles"
validate: CKEDITOR.dialog.validate.inlineStyle(editor.lang.common.invalidInlineStyle)
setup: setupAdvParams
commit: commitAdvParams
}
]
}
]
}
]
}
]
onShow: ->
editor = @getParentEditor()
selection = editor.getSelection()
element = null
# Fill in all the relevant fields if there's already one link selected.
if (element = plugin.getSelectedLink(editor)) and element.hasAttribute("href")
selection.selectElement element
else
element = null
@setupContent parseLink.apply(this, [
editor
element
])
return
onOk: ->
attributes = {}
removeAttributes = []
data = {}
me = this
editor = @getParentEditor()
@commitContent data
# Compose the URL.
switch data.type or "url"
when "url"
protocol = (if (data.url and data.url.protocol isnt `undefined`) then data.url.protocol else "http://")
url = (data.url and CKEDITOR.tools.trim(data.url.url)) or ""
attributes["data-cke-saved-href"] = (if (url.indexOf("/") is 0) then url else protocol + url)
when "localPage" # added by @simo - http://blog.xoundboy.com/?p=393
attributes["data-cke-saved-href"] = data.localPage
when "anchor"
name = (data.anchor and data.anchor.name)
id = (data.anchor and data.anchor.id)
attributes["data-cke-saved-href"] = "#" + (name or id or "")
when "email"
linkHref = undefined
email = data.email
address = email.address
switch emailProtection
when "", "encode"
subject = encodeURIComponent(email.subject or "")
body = encodeURIComponent(email.body or "")
# Build the e-mail parameters first.
argList = []
subject and argList.push("subject=" + subject)
body and argList.push("body=" + body)
argList = (if argList.length then "?" + argList.join("&") else "")
if emailProtection is "encode"
linkHref = [
"javascript:void(location.href='mailto:'+"
protectEmailAddressAsEncodedString(address)
]
# parameters are optional.
argList and linkHref.push("+'", escapeSingleQuote(argList), "'")
linkHref.push ")"
else
linkHref = [
"mailto:"
address
argList
]
break
else
# Separating name and domain.
nameAndDomain = address.split("@", 2)
email.name = nameAndDomain[0]
email.domain = nameAndDomain[1]
linkHref = [
"javascript:"
protectEmailLinkAsFunction(email)
]
attributes["data-cke-saved-href"] = linkHref.join("")
# Popups and target.
if data.target
if data.target.type is "popup"
onclickList = [
"window.open(this.href, '"
data.target.name or ""
"', '"
]
featureList = [
"resizable"
"status"
"location"
"toolbar"
"menubar"
"fullscreen"
"scrollbars"
"dependent"
]
featureLength = featureList.length
addFeature = (featureName) ->
featureList.push featureName + "=" + data.target[featureName] if data.target[featureName]
return
i = 0
while i < featureLength
featureList[i] = featureList[i] + ((if data.target[featureList[i]] then "=yes" else "=no"))
i++
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 isnt "notSet" and data.target.name
attributes.target = data.target.name
else
removeAttributes.push "target"
removeAttributes.push "data-cke-pa-onclick", "onclick"
# Advanced attributes.
if data.adv
advAttr = (inputName, attrName) ->
value = data.adv[inputName]
if value
attributes[attrName] = value
else
removeAttributes.push attrName
return
advAttr "advId", "id"
advAttr "advLangDir", "dir"
advAttr "advAccessKey", "accessKey"
if data.adv["advName"]
attributes["name"] = attributes["data-cke-saved-name"] = data.adv["advName"]
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"
selection = editor.getSelection()
# Browser need the "href" fro copy/paste link to work. (#6641)
attributes.href = attributes["data-cke-saved-href"]
unless @_.selectedElement
range = selection.getRanges(1)[0]
# Use link URL as text with a collapsed cursor.
if range.collapsed
# Short mailto link text view (#5736).
text = new CKEDITOR.dom.text((if data.type is "email" then data.email.address else attributes["data-cke-saved-href"]), editor.document)
range.insertNode text
range.selectNodeContents text
# Apply style.
style = new CKEDITOR.style(
element: "a"
attributes: attributes
)
style.type = CKEDITOR.STYLE_INLINE # need to override... dunno why.
style.applyToRange range
range.select()
else
# We're only editing an existing link, so just overwrite the attributes.
element = @_.selectedElement
href = element.data("cke-saved-href")
textView = element.getHtml()
element.setAttributes attributes
element.removeAttributes removeAttributes
element.addClass (if element.getChildCount() then "cke_anchor" else "cke_anchor_empty") if data.adv and data.adv.advName and CKEDITOR.plugins.link.synAnchorSelector
# Update text view when user changes protocol (#4612).
# Short mailto link text view (#5736).
element.setHtml (if data.type is "email" then data.email.address else attributes["data-cke-saved-href"]) if href is textView or data.type is "email" and textView.indexOf("@") isnt -1
selection.selectElement element
delete @_.selectedElement
return
onLoad: ->
@hidePage "advanced" unless editor.config.linkShowAdvancedTab #Hide Advanded tab.
@hidePage "target" unless editor.config.linkShowTargetTab #Hide Target tab.
return
# Inital focus on 'url' field if link is of type URL.
onFocus: ->
linkType = @getContentElement("info", "linkType")
urlField = undefined
if linkType and linkType.getValue() is "url"
urlField = @getContentElement("info", "url")
urlField.select()
return
# The e-mail address anti-spam protection option. The protection will be
# applied when creating or modifying e-mail links through the editor interface.
#
# Two methods of protection can be choosed:
#
# 1. The e-mail parts (name, domain and any other query string) are
# assembled into a function call pattern. Such function must be
# provided by the developer in the pages that will use the contents.
# 2. Only the e-mail address is obfuscated into a special string that
# has no meaning for humans or spam bots, but which is properly
# rendered and accepted by the browser.
#
# Both approaches require JavaScript to be enabled.
#
# // href="mailto:tester@ckeditor.com?subject=subject&body=body"
# config.emailProtection = '';
#
# // href="<a href=\"javascript:void(location.href=\'mailto:\'+String.fromCharCode(116,101,115,116,101,114,64,99,107,101,100,105,116,111,114,46,99,111,109)+\'?subject=subject&body=body\')\">e-mail</a>"
# config.emailProtection = 'encode';
#
# // href="javascript:mt('tester','ckeditor.com','subject','body')"
# config.emailProtection = 'mt(NAME,DOMAIN,SUBJECT,BODY)';
#
# @since 3.1
# @cfg {String} [emailProtection='' (empty string = disabled)]
# @member CKEDITOR.config