새로운 요소를 동적으로 추가하려던 중 WrongDocumentError 이런 오류를 만났는데....
크롬에선 잘 되는데 익스플로러 11버전에서는 안되더군요.
일단 여기 저기 다 찾아다녀 본 결과 IE 에서만 발생하는 듯 합니다.
발생 원인.
Element 를 생성한 Document 와 insert 하는 Element 가 존재하는 Document 가 서로 달라서 발생하는 것.
고로 저처럼 IFRAME 안의 내용을 주무르려고 하다보면 충분히 발생할 수 있겠네요. ( range.insertNode 등의 명령 실행 등 )
간단한 해결 방법.
- jquery 를 이용하여 그냥 element 를 생성하면 기본 window 의 document 에서 생성되므로
자바스크립트를 사용하여 생성되는 document 변경.
<기존 소스>
var $span = $('<span>'+selectedText+'</span>');
$eBody[0].ownerDocument.defaultView.getSelection().getRangeAt(0).insertNode($span[0]);
<해결 소스>
var span = cWindow.document.createElement('span');
var $span = $(span).html(selectedText);
$eBody[0].ownerDocument.defaultView.getSelection().getRangeAt(0).insertNode($span[0]);
전체 소스
<%@ page contentType="text/html;charset=UTF-8"%>
<html>
<head>
<script type="text/javascript" src="/js/ext/jquery-1.11.1.js"></script>
<script>
$.fn.copyCSS = function (source) {
var dom = $(source).get(0);
var dest = {};
var style, prop, prCss, prStyle = [];
if (window.getComputedStyle) {
var camelize = function (a, b) {
return b.toUpperCase();
};
// if (style = window.getComputedStyle(dom.parentNode, null)) {
if (style = window.getComputedStyle(dom, null)) {
// if (style = $(source)[0].style) {
var camel, val;
prCss = window.getComputedStyle(dom.parentNode, null);
for(var i=0;i<prCss.length;i++){
if(prCss.getPropertyValue(prCss[i])){
prStyle[i] = prCss[i]+':'+prCss.getPropertyValue(prCss[i]);
}
}
if (style.length) {
for (var i = 0, l = style.length; i < l; i++) {
// console.log("style["+i+"] : "+style[i]+", prStyle["+i+"] : "+prStyle[i]);
prop = style[i];
camel = prop.replace(/\-([a-z])/, camelize);
val = style.getPropertyValue(prop);
if((prop+":"+val!=prStyle[i] || prop == "font-weight") && prop.indexOf("origin") < 0) {
console.log("["+prop+" : "+val+"]");
dest[camel] = val;
}
}
} else {
for (prop in style) {
camel = prop.replace(/\-([a-z])/, camelize);
val = style.getPropertyValue(prop) || style[prop];
dest[camel] = val;
}
}
return this.css(dest);
}
}
if (style = dom.currentStyle) {
for (prop in style) {
dest[prop] = style[prop];
}
return this.css(dest);
}
if (style = dom.style) {
for (prop in style) {
if (typeof style[prop] != 'function') {
dest[prop] = style[prop];
}
}
}
return this.css(dest);
};
var tempClone = null;
function testFunction() {
// $('#content').html(function() {
// return $(this).html().replace(selectedText,mText);
// });
// selRange = "1234566";
// alert(selRange);
var selRange = getSelRange();
console.log("selRange.anchorNode >>> "+selRange.anchorNode.nodeName);
console.log("selRange.anchorOffset >>> "+selRange.anchorOffset);
console.log("selRange.focusNode >>> "+selRange.focusNode.nodeName);
console.log("selRange.focusOffset >>> "+selRange.focusOffset);
console.log("selRange.isCollapsed >>> "+selRange.isCollapsed);
console.log("selRange.rangeCount >>> "+selRange.rangeCount);
event.stopPropagation();
event.preventDefault();
}
$(function() {
var $eBody = $('#content');
var $btn = $('<div class="testBtn"><button onclick="testFunction()">click!</button><div>');
$eBody.append($btn);
var isPress = false;
$( "body" ).keydown(function( event ) {
if(event.which == 17) { // ctrl
isPress = true;
}
});
$( "body" ).keyup(function( event ) {
if(event.which == 17) { // ctrl
isPress = false;
$eBody.find('*').removeClass("selectedBox");
}
});
$eBody.on('mouseover' ,'*', function(event) {
if(isPress) {
$eBody.find('*').removeClass("selectedBox");
$(this).addClass("selectedBox");
event.stopPropagation();
}
});
$eBody.on('mousedown', '*', function(event) {
if(isPress) {
$(this).removeClass("selectedBox");
selRange = getSelRange();
var range = selRange.getRangeAt(0);
var selectedText = selRange.toString();
var $span = $('<span>'+selectedText+'</span>');
$span.copyCSS(event.target);
selRange.deleteFromDocument();
selRange.removeAllRanges();
range.insertNode($span[0]);
event.stopPropagation();
event.preventDefault();
isPress = false;
}
});
$eBody.on('click', '*', function(event) {
if(isPress) {
/*
$(this).removeClass("selectedBox");
// tempClone = $(this).clone();
// $(this).after(tempClone);
// console.log('선택영역 >>> '+getSelectionText());
alert(selRange);
var range = selRange.getRangeAt(0);
var selectedText = selRange.toString();
var $span = $('<span>'+selectedText+'</span>');
$span.copyCSS(event.target);
selRange.removeAllRanges();
range.insertNode($span);
// var tetem = $(this);
// var tete = $(this)[0].style;
// $.each(tete, function(i, k) {
// alert(i+"]"+k+", "+tetem.css(k));
// });
*/
}else{
// if(!selRange.isCollapsed) {
// alert(selRange);
// }
// selectedText = getSelectionText();
// selRange = getSelRange();
// tempClone.html(selectedText);
// mText = $('<div>').append(tempClone).html();
// console.log(event.target.nodeName+'>>> '+ mText);
// console.log(event.target.nodeName+'>>> '+selectedText);
}
event.stopPropagation();
event.preventDefault();
});
// $('#content').html(" ○ 테스트입니다.<br/> ○ 테스트입니다.<br/><br/>");
if(window.clipboardData) {
var isPress = false;
$( "body" ).keydown(function( event ) {
if(event.which == 17) { // ctrl
isPress = true;
}else{
if(isPress && event.which == 86) { // v
var c_text = window.clipboardData.getData("Text");
// console.log("원본: "+c_text);
c_text = c_text.replace(/\n/gi,"<br/>");
c_text = c_text.replace(/\s/gi," ");
$('#content').html(c_text);
// console.log(c_text);
// alert("pressed : "+event.which);
}else if(isPress && event.which == 53) { //5
if(tempClone) {
var selRange = getSelRange();
// console.log("selRange.anchorNode >>> "+selRange.anchorNode.nodeName);
// console.log("selRange.anchorOffset >>> "+selRange.anchorOffset);
// console.log("selRange.focusNode >>> "+selRange.focusNode.nodeName);
// console.log("selRange.focusOffset >>> "+selRange.focusOffset);
// console.log("selRange.isCollapsed >>> "+selRange.isCollapsed);
// console.log("selRange.rangeCount >>> "+selRange.rangeCount);
var range = window.getSelection().getRangeAt(0);
var selectedText = getSelectionText();
// range.extractContents();
// selRange.deleteFromDocument();
// var span = document.createElement("span");
// span.className= "reddy";
// span.appendChild(selectedText);
tempClone.html(selectedText);
mText = $('<div>').append(tempClone).html();
console.log(event.target.nodeName+'>>> '+ mText);
console.log(event.target.nodeName+'>>> '+selectedText);
selRange.removeAllRanges();
range.insertNode(tempClone[0]);
}
event.stopPropagation();
event.preventDefault();
}else if(isPress && event.which == 49) { //1
// alert("select >>> "+getSelectionText());
var $dd = $('<span class="testClass"></span>');
var $d1 = $('<span>asdfasdfasdfasdf</span>');
$('body').append($d1);
// $('#content').wrapInner($dd);
var tempT = getSelectionText();
alert(tempT);
$dd.html(tempT);
var tempHtml = $('<div>').append($dd).html();
alert(tempHtml);
$('#content').html(function() {
return $(this).html().replace(tempT,tempHtml);
});
event.stopPropagation();
event.preventDefault();
}else{
isPress = false;
}
}
});
}
});
function getSelectionText(e) {
var el = e || window;
var text = "";
if (el.getSelection) {
// alert(1);
text = el.getSelection().toString();
} else if (el.document.selection && el.document.selection.type != "Control") {
// alert(2);
text = el.document.selection.createRange().text;
}
return text;
}
function getSelRange(e) {
var el = e || window;
var range = "";
if (el.getSelection) {
range = el.getSelection();
} else if (el.document.selection && el.document.selection.type != "Control") {
range = el.document.selection.createRange();
}
return range;
}
//현재 커서 위치에 텍스트 대체하기
function setTextCurrentCursor(intoElement, text) {
$(intoElement).focus();
var selRange = getSelRange();
selRange = text;
alert(selRange);
}
</script>
<style type="text/css">
.testClass {margin:0;padding:0;font-size:2em;line-height:2.2em;font-family:'돋움','Dotum',sans-serif;color:#f22;vertical-align:middle}
.testBtn {position:absolute; top:0px; left:800px; width:150px; height:50px;}
.selectedBox, .reddy {border:solid red 2px !important; }
}
</style>
</head>
<body contenteditable="true">
<div id='target'>2가나다라</div>
<div id='content'>
<p style="line-height: 1.5; font-family: 맑은 고딕; font-size: 14pt; margin-top: 0px; margin-bottom: 0px;">특<strong>수문</strong>자 사용 테스트합니다~!@#$%^&*()_+|}{:?<<strong><span style="border: currentColor; border-image: none; color: rgb(255, 0, 0); font-family: 맑은 고딕; font-size: 14pt; margin-top: 0px; margin-bottom: 0px;">123</span></strong>> : 골뱅이 포함</p>
<p style="line-height: 1.5; font-family: 맑은 고딕; font-size: 14pt; margin-top: 0px; margin-bottom: 0px;">특수문자 사용 <span style="color: rgb(255, 0, 0); font-family: 맑은 고딕; font-size: 14pt; margin-top: 0px; margin-bottom: 0px;">테스트</span>합니다~!#$%^&*()_+|}{:?<<strong><span style="color: rgb(9, 0, 255); font-family: 맑은 고딕; font-size: 14pt; margin-top: 0px; margin-bottom: 0px;">허허허</span></strong>> : 골뱅이 미포함</p>
</div>
</body>
</html>
'Dev. 웹' 카테고리의 다른 글
Velocity 사용하기 (0) | 2015.04.29 |
---|---|
[Custom Tag] custom tag 작성 중 SimpleTagSupport 에서의 세션 가져오기 (0) | 2014.10.28 |
JSTL (JSP Standard Tag Library) 시작하기 - 이해 및 실습 (0) | 2014.10.14 |
ajax 사용하기 (문법, 파라미터) (0) | 2013.05.31 |
JavaScript and HTML DOM(Document Object Model) - 웹의 객체 구조화 (0) | 2012.09.11 |