### @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: "