Page Menu
Home
Code
Search
Configure Global Search
Log In
Files
F885718
range.js
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
15 KB
Subscribers
None
range.js
View Options
if
(
!
dojo
.
_hasResource
[
"dijit._editor.range"
]){
//_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo
.
_hasResource
[
"dijit._editor.range"
]
=
true
;
dojo
.
provide
(
"dijit._editor.range"
);
dijit
.
range
=
{};
dijit
.
range
.
getIndex
=
function
(
/*DomNode*/
node
,
/*DomNode*/
parent
){
// dojo.profile.start("dijit.range.getIndex");
var
ret
=
[],
retR
=
[];
var
stop
=
parent
;
var
onode
=
node
;
while
(
node
!=
stop
){
var
i
=
0
;
var
pnode
=
node
.
parentNode
,
n
;
while
(
n
=
pnode
.
childNodes
[
i
++
]){
if
(
n
===
node
){
--
i
;
break
;
}
}
if
(
i
>=
pnode
.
childNodes
.
length
){
dojo
.
debug
(
"Error finding index of a node in dijit.range.getIndex"
);
}
ret
.
unshift
(
i
);
retR
.
unshift
(
i
-
pnode
.
childNodes
.
length
);
node
=
pnode
;
}
//normalized() can not be called so often to prevent
//invalidating selection/range, so we have to detect
//here that any text nodes in a row
if
(
ret
.
length
>
0
&&
onode
.
nodeType
==
3
){
var
n
=
onode
.
previousSibling
;
while
(
n
&&
n
.
nodeType
==
3
){
ret
[
ret
.
length
-
1
]
--
;
n
=
n
.
previousSibling
;
}
n
=
onode
.
nextSibling
;
while
(
n
&&
n
.
nodeType
==
3
){
retR
[
retR
.
length
-
1
]
++
;
n
=
n
.
nextSibling
;
}
}
// dojo.profile.end("dijit.range.getIndex");
return
{
o
:
ret
,
r
:
retR
};
}
dijit
.
range
.
getNode
=
function
(
/*Array*/
index
,
/*DomNode*/
parent
){
if
(
!
dojo
.
isArray
(
index
)
||
index
.
length
==
0
){
return
parent
;
}
var
node
=
parent
;
// if(!node)debugger
dojo
.
every
(
index
,
function
(
i
){
if
(
i
>=
0
&&
i
<
node
.
childNodes
.
length
){
node
=
node
.
childNodes
[
i
];
}
else
{
node
=
null
;
console
.
debug
(
'Error: can not find node with index'
,
index
,
'under parent node'
,
parent
);
return
false
;
//terminate dojo.every
}
return
true
;
//carry on the every loop
});
return
node
;
}
dijit
.
range
.
getCommonAncestor
=
function
(
n1
,
n2
,
root
){
var
getAncestors
=
function
(
n
,
root
){
var
as
=
[];
while
(
n
){
as
.
unshift
(
n
);
if
(
n
!=
root
&&
n
.
tagName
!=
'BODY'
){
n
=
n
.
parentNode
;
}
else
{
break
;
}
}
return
as
;
};
var
n1as
=
getAncestors
(
n1
,
root
);
var
n2as
=
getAncestors
(
n2
,
root
);
var
m
=
Math
.
min
(
n1as
.
length
,
n2as
.
length
);
var
com
=
n1as
[
0
];
//at least, one element should be in the array: the root (BODY by default)
for
(
var
i
=
1
;
i
<
m
;
i
++
){
if
(
n1as
[
i
]
===
n2as
[
i
]){
com
=
n1as
[
i
]
}
else
{
break
;
}
}
return
com
;
}
dijit
.
range
.
getAncestor
=
function
(
/*DomNode*/
node
,
/*RegEx?*/
regex
,
/*DomNode?*/
root
){
root
=
root
||
node
.
ownerDocument
.
body
;
while
(
node
&&
node
!==
root
){
var
name
=
node
.
nodeName
.
toUpperCase
()
;
if
(
regex
.
test
(
name
)){
return
node
;
}
node
=
node
.
parentNode
;
}
return
null
;
}
dijit
.
range
.
BlockTagNames
=
/^(?:P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DT|DE)$/
;
dijit
.
range
.
getBlockAncestor
=
function
(
/*DomNode*/
node
,
/*RegEx?*/
regex
,
/*DomNode?*/
root
){
root
=
root
||
node
.
ownerDocument
.
body
;
regex
=
regex
||
dijit
.
range
.
BlockTagNames
;
var
block
=
null
,
blockContainer
;
while
(
node
&&
node
!==
root
){
var
name
=
node
.
nodeName
.
toUpperCase
()
;
if
(
!
block
&&
regex
.
test
(
name
)){
block
=
node
;
}
if
(
!
blockContainer
&&
(
/^(?:BODY|TD|TH|CAPTION)$/
).
test
(
name
)){
blockContainer
=
node
;
}
node
=
node
.
parentNode
;
}
return
{
blockNode
:
block
,
blockContainer
:
blockContainer
||
node
.
ownerDocument
.
body
};
}
dijit
.
range
.
atBeginningOfContainer
=
function
(
/*DomNode*/
container
,
/*DomNode*/
node
,
/*Int*/
offset
){
var
atBeginning
=
false
;
var
offsetAtBeginning
=
(
offset
==
0
);
if
(
!
offsetAtBeginning
&&
node
.
nodeType
==
3
){
//if this is a text node, check whether the left part is all space
if
(
dojo
.
trim
(
node
.
nodeValue
.
substr
(
0
,
offset
))
==
0
){
offsetAtBeginning
=
true
;
}
}
if
(
offsetAtBeginning
){
var
cnode
=
node
;
atBeginning
=
true
;
while
(
cnode
&&
cnode
!==
container
){
if
(
cnode
.
previousSibling
){
atBeginning
=
false
;
break
;
}
cnode
=
cnode
.
parentNode
;
}
}
return
atBeginning
;
}
dijit
.
range
.
atEndOfContainer
=
function
(
/*DomNode*/
container
,
/*DomNode*/
node
,
/*Int*/
offset
){
var
atEnd
=
false
;
var
offsetAtEnd
=
(
offset
==
(
node
.
length
||
node
.
childNodes
.
length
));
if
(
!
offsetAtEnd
&&
node
.
nodeType
==
3
){
//if this is a text node, check whether the right part is all space
if
(
dojo
.
trim
(
node
.
nodeValue
.
substr
(
offset
))
==
0
){
offsetAtEnd
=
true
;
}
}
if
(
offsetAtEnd
){
var
cnode
=
node
;
atEnd
=
true
;
while
(
cnode
&&
cnode
!==
container
){
if
(
cnode
.
nextSibling
){
atEnd
=
false
;
break
;
}
cnode
=
cnode
.
parentNode
;
}
}
return
atEnd
;
}
dijit
.
range
.
adjacentNoneTextNode
=
function
(
startnode
,
next
){
var
node
=
startnode
;
var
len
=
(
0
-
startnode
.
length
)
||
0
;
var
prop
=
next
?
'nextSibling'
:
'previousSibling'
;
while
(
node
){
if
(
node
.
nodeType
!=
3
){
break
;
}
len
+=
node
.
length
node
=
node
[
prop
];
}
return
[
node
,
len
];
}
dijit
.
range
.
_w3c
=
Boolean
(
window
[
'getSelection'
]);
dijit
.
range
.
create
=
function
(){
if
(
dijit
.
range
.
_w3c
){
return
document
.
createRange
();
}
else
{
//IE
return
new
dijit
.
range
.
W3CRange
;
}
}
dijit
.
range
.
getSelection
=
function
(
win
,
/*Boolean?*/
ignoreUpdate
){
if
(
dijit
.
range
.
_w3c
){
return
win
.
getSelection
();
}
else
{
//IE
var
id
=
win
.
__W3CRange
;
if
(
!
id
||
!
dijit
.
range
.
ie
.
cachedSelection
[
id
]){
var
s
=
new
dijit
.
range
.
ie
.
selection
(
win
);
//use win as the key in an object is not reliable, which
//can leads to quite odd behaviors. thus we generate a
//string and use it as a key in the cache
id
=
(
new
Date
).
getTime
();
while
(
id
in
dijit
.
range
.
ie
.
cachedSelection
){
id
=
id
+
1
;
}
id
=
String
(
id
);
dijit
.
range
.
ie
.
cachedSelection
[
id
]
=
s
;
}
else
{
var
s
=
dijit
.
range
.
ie
.
cachedSelection
[
id
];
}
if
(
!
ignoreUpdate
){
s
.
_getCurrentSelection
();
}
return
s
;
}
}
if
(
!
dijit
.
range
.
_w3c
){
dijit
.
range
.
ie
=
{
cachedSelection
:
{},
selection
:
function
(
win
){
this
.
_ranges
=
[];
this
.
addRange
=
function
(
r
,
/*boolean*/
internal
){
this
.
_ranges
.
push
(
r
);
if
(
!
internal
){
r
.
_select
();
}
this
.
rangeCount
=
this
.
_ranges
.
length
;
};
this
.
removeAllRanges
=
function
(){
//don't detach, the range may be used later
// for(var i=0;i<this._ranges.length;i++){
// this._ranges[i].detach();
// }
this
.
_ranges
=
[];
this
.
rangeCount
=
0
;
};
var
_initCurrentRange
=
function
(){
var
r
=
win
.
document
.
selection
.
createRange
();
var
type
=
win
.
document
.
selection
.
type
.
toUpperCase
();
if
(
type
==
"CONTROL"
){
//TODO: multiple range selection(?)
return
new
dijit
.
range
.
W3CRange
(
dijit
.
range
.
ie
.
decomposeControlRange
(
r
));
}
else
{
return
new
dijit
.
range
.
W3CRange
(
dijit
.
range
.
ie
.
decomposeTextRange
(
r
));
}
};
this
.
getRangeAt
=
function
(
i
){
return
this
.
_ranges
[
i
];
};
this
.
_getCurrentSelection
=
function
(){
this
.
removeAllRanges
();
var
r
=
_initCurrentRange
();
if
(
r
){
this
.
addRange
(
r
,
true
);
}
};
},
decomposeControlRange
:
function
(
range
){
var
firstnode
=
range
.
item
(
0
),
lastnode
=
range
.
item
(
range
.
length
-
1
)
var
startContainer
=
firstnode
.
parentNode
,
endContainer
=
lastnode
.
parentNode
;
var
startOffset
=
dijit
.
range
.
getIndex
(
firstnode
,
startContainer
).
o
;
var
endOffset
=
dijit
.
range
.
getIndex
(
lastnode
,
endContainer
).
o
+
1
;
return
[[
startContainer
,
startOffset
],[
endContainer
,
endOffset
]];
},
getEndPoint
:
function
(
range
,
end
){
var
atmrange
=
range
.
duplicate
();
atmrange
.
collapse
(
!
end
);
var
cmpstr
=
'EndTo'
+
(
end
?
'End'
:
'Start'
);
var
parentNode
=
atmrange
.
parentElement
();
var
startnode
,
startOffset
,
lastNode
;
if
(
parentNode
.
childNodes
.
length
>
0
){
dojo
.
every
(
parentNode
.
childNodes
,
function
(
node
,
i
){
var
calOffset
;
if
(
node
.
nodeType
!=
3
){
atmrange
.
moveToElementText
(
node
);
if
(
atmrange
.
compareEndPoints
(
cmpstr
,
range
)
>
0
){
startnode
=
node
.
previousSibling
;
if
(
lastNode
&&
lastNode
.
nodeType
==
3
){
//where share we put the start? in the text node or after?
startnode
=
lastNode
;
calOffset
=
true
;
}
else
{
startnode
=
parentNode
;
startOffset
=
i
;
return
false
;
}
}
else
{
if
(
i
==
parentNode
.
childNodes
.
length
-
1
){
startnode
=
parentNode
;
startOffset
=
parentNode
.
childNodes
.
length
;
return
false
;
}
}
}
else
{
if
(
i
==
parentNode
.
childNodes
.
length
-
1
){
//at the end of this node
startnode
=
node
;
calOffset
=
true
;
}
}
// try{
if
(
calOffset
&&
startnode
){
var
prevnode
=
dijit
.
range
.
adjacentNoneTextNode
(
startnode
)[
0
];
if
(
prevnode
){
startnode
=
prevnode
.
nextSibling
;
}
else
{
startnode
=
parentNode
.
firstChild
;
//firstChild must be a text node
}
var
prevnodeobj
=
dijit
.
range
.
adjacentNoneTextNode
(
startnode
);
prevnode
=
prevnodeobj
[
0
];
var
lenoffset
=
prevnodeobj
[
1
];
if
(
prevnode
){
atmrange
.
moveToElementText
(
prevnode
);
atmrange
.
collapse
(
false
);
}
else
{
atmrange
.
moveToElementText
(
parentNode
);
}
atmrange
.
setEndPoint
(
cmpstr
,
range
);
startOffset
=
atmrange
.
text
.
length
-
lenoffset
;
return
false
;
}
// }catch(e){ debugger }
lastNode
=
node
;
return
true
;
});
}
else
{
startnode
=
parentNode
;
startOffset
=
0
;
}
//if at the end of startnode and we are dealing with start container, then
//move the startnode to nextSibling if it is a text node
//TODO: do this for end container?
if
(
!
end
&&
startnode
.
nodeType
!=
3
&&
startOffset
==
startnode
.
childNodes
.
length
){
if
(
startnode
.
nextSibling
&&
startnode
.
nextSibling
.
nodeType
==
3
){
startnode
=
startnode
.
nextSibling
;
startOffset
=
0
;
}
}
return
[
startnode
,
startOffset
];
},
setEndPoint
:
function
(
range
,
container
,
offset
){
//text node
var
atmrange
=
range
.
duplicate
();
if
(
container
.
nodeType
!=
3
){
//normal node
atmrange
.
moveToElementText
(
container
);
atmrange
.
collapse
(
true
);
if
(
offset
==
container
.
childNodes
.
length
){
if
(
offset
>
0
){
//a simple atmrange.collapse(false); won't work here:
//although moveToElementText(node) is supposed to encompass the content of the node,
//but when collapse to end, it is in fact after the ending tag of node (collapse to start
//is after the begining tag of node as expected)
var
node
=
container
.
lastChild
;
var
len
=
0
;
while
(
node
&&
node
.
nodeType
==
3
){
len
+=
node
.
length
;
container
=
node
;
//pass through
node
=
node
.
previousSibling
;
}
if
(
node
){
atmrange
.
moveToElementText
(
node
);
}
atmrange
.
collapse
(
false
);
offset
=
len
;
//pass through
}
else
{
//no childNodes
atmrange
.
moveToElementText
(
container
);
atmrange
.
collapse
(
true
);
}
}
else
{
if
(
offset
>
0
){
var
node
=
container
.
childNodes
[
offset
-
1
];
if
(
node
.
nodeType
==
3
){
container
=
node
;
offset
=
node
.
length
;
//pass through
}
else
{
atmrange
.
moveToElementText
(
node
);
atmrange
.
collapse
(
false
);
}
}
}
}
if
(
container
.
nodeType
==
3
){
var
prevnodeobj
=
dijit
.
range
.
adjacentNoneTextNode
(
container
);
var
prevnode
=
prevnodeobj
[
0
],
len
=
prevnodeobj
[
1
];
if
(
prevnode
){
atmrange
.
moveToElementText
(
prevnode
);
atmrange
.
collapse
(
false
);
//if contentEditable is not inherit, the above collapse won't make the end point
//in the correctly position: it always has a -1 offset, so compensate it
if
(
prevnode
.
contentEditable
!=
'inherit'
){
len
++
;
}
}
else
{
atmrange
.
moveToElementText
(
container
.
parentNode
);
atmrange
.
collapse
(
true
);
}
offset
+=
len
;
if
(
offset
>
0
){
if
(
atmrange
.
moveEnd
(
'character'
,
offset
)
!=
offset
){
alert
(
'Error when moving!'
);
}
atmrange
.
collapse
(
false
);
}
}
return
atmrange
;
},
decomposeTextRange
:
function
(
range
){
var
tmpary
=
dijit
.
range
.
ie
.
getEndPoint
(
range
);
var
startContainter
=
tmpary
[
0
],
startOffset
=
tmpary
[
1
];
var
endContainter
=
tmpary
[
0
],
endOffset
=
tmpary
[
1
];
if
(
range
.
htmlText
.
length
){
if
(
range
.
htmlText
==
range
.
text
){
//in the same text node
endOffset
=
startOffset
+
range
.
text
.
length
;
}
else
{
tmpary
=
dijit
.
range
.
ie
.
getEndPoint
(
range
,
true
);
endContainter
=
tmpary
[
0
],
endOffset
=
tmpary
[
1
];
}
}
return
[[
startContainter
,
startOffset
],[
endContainter
,
endOffset
],
range
.
parentElement
()];
},
setRange
:
function
(
range
,
startContainter
,
startOffset
,
endContainter
,
endOffset
,
check
){
var
startrange
=
dijit
.
range
.
ie
.
setEndPoint
(
range
,
startContainter
,
startOffset
);
range
.
setEndPoint
(
'StartToStart'
,
startrange
);
if
(
!
this
.
collapsed
){
var
endrange
=
dijit
.
range
.
ie
.
setEndPoint
(
range
,
endContainter
,
endOffset
);
range
.
setEndPoint
(
'EndToEnd'
,
endrange
);
}
return
range
;
}
}
dojo
.
declare
(
"dijit.range.W3CRange"
,
null
,
{
constructor
:
function
(){
if
(
arguments
.
length
>
0
){
this
.
setStart
(
arguments
[
0
][
0
][
0
],
arguments
[
0
][
0
][
1
]);
this
.
setEnd
(
arguments
[
0
][
1
][
0
],
arguments
[
0
][
1
][
1
],
arguments
[
0
][
2
]);
}
else
{
this
.
commonAncestorContainer
=
null
;
this
.
startContainer
=
null
;
this
.
startOffset
=
0
;
this
.
endContainer
=
null
;
this
.
endOffset
=
0
;
this
.
collapsed
=
true
;
}
},
_simpleSetEndPoint
:
function
(
node
,
range
,
end
){
var
r
=
(
this
.
_body
||
node
.
ownerDocument
.
body
).
createTextRange
();
if
(
node
.
nodeType
!=
1
){
r
.
moveToElementText
(
node
.
parentNode
);
}
else
{
r
.
moveToElementText
(
node
);
}
r
.
collapse
(
true
);
range
.
setEndPoint
(
end
?
'EndToEnd'
:
'StartToStart'
,
r
);
},
_updateInternal
:
function
(
__internal_common
){
if
(
this
.
startContainer
!==
this
.
endContainer
){
if
(
!
__internal_common
){
var
r
=
(
this
.
_body
||
this
.
startContainer
.
ownerDocument
.
body
).
createTextRange
();
this
.
_simpleSetEndPoint
(
this
.
startContainer
,
r
);
this
.
_simpleSetEndPoint
(
this
.
endContainer
,
r
,
true
);
__internal_common
=
r
.
parentElement
();
}
this
.
commonAncestorContainer
=
dijit
.
range
.
getCommonAncestor
(
this
.
startContainer
,
this
.
endContainer
,
__internal_common
);
}
else
{
this
.
commonAncestorContainer
=
this
.
startContainer
;
}
this
.
collapsed
=
(
this
.
startContainer
===
this
.
endContainer
)
&&
(
this
.
startOffset
==
this
.
endOffset
);
},
setStart
:
function
(
node
,
offset
,
__internal_common
){
if
(
this
.
startContainer
===
node
&&
this
.
startOffset
==
offset
){
return
;
}
delete
this
.
_cachedBookmark
;
this
.
startContainer
=
node
;
this
.
startOffset
=
offset
;
if
(
!
this
.
endContainer
){
this
.
setEnd
(
node
,
offset
,
__internal_common
);
}
else
{
this
.
_updateInternal
(
__internal_common
);
}
},
setEnd
:
function
(
node
,
offset
,
__internal_common
){
if
(
this
.
endContainer
===
node
&&
this
.
endOffset
==
offset
){
return
;
}
delete
this
.
_cachedBookmark
;
this
.
endContainer
=
node
;
this
.
endOffset
=
offset
;
if
(
!
this
.
startContainer
){
this
.
setStart
(
node
,
offset
,
__internal_common
);
}
else
{
this
.
_updateInternal
(
__internal_common
);
}
},
setStartAfter
:
function
(
node
,
offset
){
this
.
_setPoint
(
'setStart'
,
node
,
offset
,
1
);
},
setStartBefore
:
function
(
node
,
offset
){
this
.
_setPoint
(
'setStart'
,
node
,
offset
,
0
);
},
setEndAfter
:
function
(
node
,
offset
){
this
.
_setPoint
(
'setEnd'
,
node
,
offset
,
1
);
},
setEndBefore
:
function
(
node
,
offset
){
this
.
_setPoint
(
'setEnd'
,
node
,
offset
,
0
);
},
_setPoint
:
function
(
what
,
node
,
offset
,
ext
){
var
index
=
dijit
.
range
.
getIndex
(
node
,
node
.
parentNode
).
o
;
this
[
what
](
node
.
parentNode
,
index
.
pop
()
+
ext
);
},
_getIERange
:
function
(){
var
r
=
(
this
.
_body
||
this
.
endContainer
.
ownerDocument
.
body
).
createTextRange
();
dijit
.
range
.
ie
.
setRange
(
r
,
this
.
startContainer
,
this
.
startOffset
,
this
.
endContainer
,
this
.
endOffset
);
return
r
;
},
getBookmark
:
function
(
body
){
this
.
_getIERange
();
return
this
.
_cachedBookmark
;
},
_select
:
function
(){
var
r
=
this
.
_getIERange
();
r
.
select
();
},
deleteContents
:
function
(){
var
r
=
this
.
_getIERange
();
r
.
pasteHTML
(
''
);
this
.
endContainer
=
this
.
startContainer
;
this
.
endOffset
=
this
.
startOffset
;
this
.
collapsed
=
true
;
},
cloneRange
:
function
(){
var
r
=
new
dijit
.
range
.
W3CRange
([[
this
.
startContainer
,
this
.
startOffset
],
[
this
.
endContainer
,
this
.
endOffset
]]);
r
.
_body
=
this
.
_body
;
return
r
;
},
detach
:
function
(){
this
.
_body
=
null
;
this
.
commonAncestorContainer
=
null
;
this
.
startContainer
=
null
;
this
.
startOffset
=
0
;
this
.
endContainer
=
null
;
this
.
endOffset
=
0
;
this
.
collapsed
=
true
;
}
});
}
//if(!dijit.range._w3c)
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Apr 6, 18:55 (2 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25666
Default Alt Text
range.js (15 KB)
Attached To
rZEDHG ZedLegacy
Event Timeline
Log In to Comment