1

We have a bug at this CKEditor plugin, and a generic solution is like to this, applying a generic string-filter only to terminal text nodes of the DOM.

QUESTION: how (need code example) to traverse a selection node (editor.getSelection()) by CKEditor-4 tools, like CKEDITOR.dom.range?

Peter Krauss
  • 13,174
  • 24
  • 167
  • 304
  • The answer of this question collaborated to [Aug 28, 2013 version of this plugin](https://github.com/onderceylan/ckeditor-texttransform-plugin/blob/master/plugin.js) – Peter Krauss Aug 28 '13 at 21:35

1 Answers1

4

First step will be to get ranges from current selection. To do this just call:

var ranges = editor.getSelection().getRanges();

This gives you an array of ranges, because theoretically (and this theory is proved only by Firefox) one selection can contain many ranges. But in 99% of real world cases you can just handle the first one and ignore other. So you've got range.

Now, the easiest way to iterate over each node in this range is to use CKEDITOR.dom.walker. Use it for example this way:

var walker = new CKEDITOR.dom.walker( range ),
    node;

while ( ( node = walker.next() ) ) {
    // Log values of every text node in range.
    console.log( node.type == CKEDITOR.NODE_TEXT && node.getText() );
}

However, there's a problem with text nodes at the range's boundaries. Consider following range:

<p>[foo<i>bar</i>bo]m</p>

This will log: foo, bar, and bom. Yes - entire bom, because it is a single node and walker does not modify DOM (there's a bug in documentation).

Therefore you should check every node you want to transform if it equals range's startContainer or endContainer and if yes - transform only that part of it which is inside range.

Note: I don't know walker's internals and I'm not sure whether you can modify DOM while iterating over it. I'd recommend first caching nodes and then making changes.

Reinmar
  • 21,729
  • 4
  • 67
  • 78
  • thanks a lot! About the `walker` problem... Hum... Another way is to use DOM-2 standard Javascript methods: how to get the DOM of the editing (selected) text? We can use XPath (`//text()`) or `document.querySelector`, etc. to iterate over all text nodes... And modify (after iterated all as you suggest) directally the `nodeValue` or `textContent` properties. – Peter Krauss Aug 27 '13 at 20:43
  • Another way to fix bug at the [cited plugin code](https://github.com/onderceylan/ckeditor-texttransform-plugin/blob/master/plugin.js) is by regular expression... How to get XHTML (like DOM `saveXML`)? There are a `selection.getSelectedHTML()` to replace `selection.getSelectedText()` ? – Peter Krauss Aug 27 '13 at 20:52
  • I'm sorry, but I don't understand your questions. And they seem to be unrelated to the main one. – Reinmar Aug 27 '13 at 21:01
  • The main subquestion here is about avoid `walker` (that not is a safe method!) and use another more pritive method, perhaps a Javascript native DOM method... So the subquestion: how to get "real DOM" object from selection? If I have a "pure DOM node" (not an extended class of CKEditor), I can traverse by traditional standard Javascript. – Peter Krauss Aug 27 '13 at 21:11
  • When I am trying to implement with `walk` as you suggested, I not see how to modify nodes: [CKEDITOR.dom.node](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.node) not show `getText()`, that works, method neither an "putText", that I need. – Peter Krauss Aug 27 '13 at 21:42
  • Come on... I pointed you the API docs and you haven't found it? [CKEDITOR.dom.node](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.node) has two subclasses - [CKEDITOR.dom.text](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.text), [CKEDITOR.dom.element](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.element). You can also get the native DOM nodes by accessing `node.$` and then use e.g. jQuery. – Reinmar Aug 28 '13 at 07:44
  • And I don't have ANY idea what do you mean by "avoid walker (that not is a safe method!)". – Reinmar Aug 28 '13 at 07:45
  • Thank you for showing the road! Now I undertanding the CKEditor's framework (!), I can use basic DOM as `node.$.textContent = "HELLO!";`. About `walker`, if I edit "`bo]m`" and editor's "to upper tool" changes to "`BOM`" (not "`BO]M`"!) it is a not safe tool... Well, that is what you say about `walker`: now I try and it works! – Peter Krauss Aug 28 '13 at 12:06