Working with ranges and selections in CKEditor is almost unbearable. In order to make it a bit easier, i recommend using rangy, a free library that makes the html selection/range api cross-browser-proof. Well, at least it made what i was trying to accomplish cross-browser...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* allows you to wrap or insert an html tag over a selection/range using rangy | |
* @param iframe the CKEditor iframe html element | |
* @param tagName string representation of the tag, such as 'a' for anchor | |
* @param withNodeFunc function to allow outside modification of the element before injecting/wrapping | |
*/ | |
function wrapOrInsert(iframe, tagName, withNodeFunc) { | |
var iframedoc = iframe.contentDocument || iframe.contentWindow.document, | |
tag = iframedoc.createElement(tagName), | |
selection = rangy.getIframeSelection(iframe), | |
selectionRange = selection.getRangeAt(0); | |
//let the caller do something with the element | |
withNodeFunc(tag); | |
//since you can't wrap something with an image tag | |
if (tagName === 'img') { | |
selectionRange.collapse(false); | |
selectionRange.insertNode(tag); | |
} else if (tagName === "a" && selection.isCollapsed) { | |
//provide some default text for an anchor | |
selectionRange.collapse(false); | |
tag.appendChild(iframedoc.createTextNode('link')); | |
selectionRange.insertNode(tag); | |
} else { | |
selectionRange.surroundContents(tag); | |
} | |
//detach rangy | |
selection.detach(); | |
} | |
/** | |
* Example on how to call the function, let's say on a jquery document.ready | |
* It'll wrap the selection in a span | |
*/ | |
$(function(){ | |
//first, lets get the iframe that the ckeditor is in | |
var iframe=$(".ckeditor iframe"); | |
//we put the [0] on the end of the jquery item, since that will cast it to a DOM element (see http://stackoverflow.com/questions/6974582/jquery-object-and-dom-element) | |
// and, we'll pass an empty callback, since we don't want to do anything with the span after its created | |
wrapOrInsert(iframe[0],"span",function(){}); | |
}); |
Hi Smith,
ReplyDeleteI am facing the same problem. Need to wrap a span around selected text in CKEditor. Need some information about the function you wrote. If I am trying my own plugin then what should be the value of iframe here in the function parameter. and in withNodeFunc we need to create an element... do we need to return anything from the function
I've updated the code-- feel free to take a look
ReplyDeletehi there, I am using the ckeditor in drupal, and I don't think it uses iframes, is this possible?
ReplyDeleteIf you're using the version of CKEDITOR that is at Drupal.ckeditor.com, then no. From what i can tell, that is an html textarea on steriods. This code is for CKEDITOR >= 3.5, the "iframe on steroids" version.
ReplyDeleteIn other words, if you inspect the HTML of your editor and don't see an iframe, this code will not work.
Thanks for asking!
that is great
ReplyDeletei also faced same issue and on this i have got solution.
thanks Micah Smith
Facebook Game Development
Is this code still valid? I'm gettin' some errors while using it (i.e. null iframedoc).
ReplyDelete