source: [view]
var ed = this.editor;
var sel = dijit.range.getSelection(ed.window);
if(sel && sel.rangeCount > 0){
var range = sel.getRangeAt(0);
var node = range.startContainer;
var tag, start, end, div;
if(range.startContainer === range.endContainer){
// No selection, just cursor point, we need to see if we're
// in an indentable block, or similar.
if(this._isRootInline(range.startContainer)){
// Text at the 'root' of the document,
// we'll try to indent it and all inline selements around it
// as they are visually a single line.
// First, we need to find the toplevel inline element that is rooted
// to the document 'editNode'
start = range.startContainer;
while(start && start.parentNode !== ed.editNode){
start = start.parentNode;
}
// Now we need to walk up its siblings and look for the first one in the rooting
// that isn't inline or text, as we want to grab all of that for indent.
while(start && start.previousSibling && (
this._isTextElement(start) ||
(start.nodeType === 1 && this._isInlineFormat(this._getTagName(start))
))){
start = start.previousSibling;
}
if(start && start.nodeType === 1 && !this._isInlineFormat(this._getTagName(start))){
// Adjust slightly, we're one node too far back in this case.
start = start.nextSibling;
}
// Okay, we have a configured start, lets grab everything following it that's
// inline and make it an indentable block!
if(start){
div = ed.document.createElement("div");
dojo.place(div, start, "after");
div.appendChild(start);
end = div.nextSibling;
while(end && (
this._isTextElement(end) ||
(end.nodeType === 1 &&
this._isInlineFormat(this._getTagName(end)))
)){
// Add it.
div.appendChild(end);
end = div.nextSibling;
}
this._indentElement(div);
dojo.withGlobal(ed.window,
"selectElementChildren", dijit._editor.selection, [div]);
dojo.withGlobal(ed.window,
"collapse", dijit._editor.selection, [true]);
}
}else{
while(node && node !== ed.document && node !== ed.editNode){
tag = this._getTagName(node);
if(tag === "li"){
this._indentList(node);
return;
}else if(this._isIndentableElement(tag)){
this._indentElement(node);
return;
}
node = node.parentNode;
}
}
}else{
var curNode;
// multi-node select. We need to scan over them.
// Find the two containing nodes at start and end.
// then move the end one node past. Then ... lets see
// what we can indent!
start = range.startContainer;
end = range.endContainer;
// Find the non-text nodes.
while(start && this._isTextElement(start) && start.parentNode !== ed.editNode){
start = start.parentNode;
}
while(end && this._isTextElement(end) && end.parentNode !== ed.editNode){
end = end.parentNode;
}
if(end === ed.editNode || end === ed.document.body){
// Okay, selection end is somewhere after start, we need to find the last node
// that is safely in the range.
curNode = start;
while(curNode.nextSibling &&
dojo.withGlobal(ed.window, "inSelection", dijit._editor.selection, [curNode])){
curNode = curNode.nextSibling;
}
end = curNode;
if(end === ed.editNode || end === ed.document.body){
// Unable to determine real selection end, so just make it
// a single node indent of start + all following inline styles, if
// present, then just exit.
tag = this._getTagName(start);
if(tag === "li"){
this._indentList(start);
}else if(this._isIndentableElement(tag)){
this._indentElement(start);
}else if(this._isTextElement(start) ||
this._isInlineFormat(tag)){
// inline element or textnode, So we want to indent it somehow
div = ed.document.createElement("div");
dojo.place(div, start, "after");
// Find and move all inline tags following the one we inserted also into the
// div so we don't split up content funny.
var next = start;
while(next && (
this._isTextElement(next) ||
(next.nodeType === 1 &&
this._isInlineFormat(this._getTagName(next))))){
div.appendChild(next);
next = div.nextSibling;
}
this._indentElement(div);
}
return;
}
}
// Has a definite end somewhere, so lets try to indent up to it.
// requires looking at the selections and in some cases, moving nodes
// into indentable blocks.
end = end.nextSibling;
curNode = start;
while(curNode && curNode !== end){
if(curNode.nodeType === 1){
tag = this._getTagName(curNode);
if(dojo.isIE){
// IE sometimes inserts blank P tags, which we want to skip
// as they end up indented, which messes up layout.
if(tag === "p" && this._isEmpty(curNode)){
curNode = curNode.nextSibling;
continue;
}
}
if(tag === "li"){
if(div){
if(this._isEmpty(div)){
div.parentNode.removeChild(div);
}else{
this._indentElement(div);
}
div = null;
}
this._indentList(curNode);
}else if(!this._isInlineFormat(tag) && this._isIndentableElement(tag)){
if(div){
if(this._isEmpty(div)){
div.parentNode.removeChild(div);
}else{
this._indentElement(div);
}
div = null;
}
curNode = this._indentElement(curNode);
}else if(this._isInlineFormat(tag)){
// inline tag.
if(!div){
div = ed.document.createElement("div");
dojo.place(div, curNode, "after");
div.appendChild(curNode);
curNode = div;
}else{
div.appendChild(curNode);
curNode = div;
}
}
}else if(this._isTextElement(curNode)){
if(!div){
div = ed.document.createElement("div");
dojo.place(div, curNode, "after");
div.appendChild(curNode);
curNode = div;
}else{
div.appendChild(curNode);
curNode = div;
}
}
curNode = curNode.nextSibling;
}
// Okay, indent everything we merged if we haven't yet..
if(div){
if(this._isEmpty(div)){
div.parentNode.removeChild(div);
}else{
this._indentElement(div);
}
div = null;
}
}
}