[JavaScript]模式窗口只读状态下复制控件文本
模式窗口只读状态下要进行复制很麻烦,无法选定文本也无法进行复制、编辑、右键浏览器菜单。本文提供一种解决这个问题的方法:使用JavaScript脚本,选定控件文本,再使用CTRL+C进行复制。
一、一些后面要用到的方法:
/*
功能: 判断是否字符串类型
参数: 无
调用方法: 对象.isString()
NOTE: (typeof(oSource) == 'string')不能正确识别new String()产生的字符串对象
*/
String.prototype.isString = String.prototype.isString || (
function() {
return ('[object String]' == Object.prototype.toString.call(this));
}
);
/*
功能: 获取控件文本。
*/
function GetControlText(oSource) {
return (oSource.innerText
|| oSource.value
|| ""); //oSource.selectorText ||
}
/*
功能: 设置控件可复制
NOTE: 选定后就可以使用Ctrl+C组合键进行复制! 但不能使用浏览器右键菜单
*/
function SetCanCopy(oSource) {
oSource.contentEditable = true;
oSource.disabled = false;//可能不需要修改?
}
判断是否字符串的方法抄自百度开源js库;获取控件文本可能还有其他情况没考虑到;设置控件contentEditable = true;不是一定需要,不过设置了可以使得选定控件文本的操作更加准确(在文本选定方法fnSelectText中体现),具体来说,就是双击控件(控件外部不算),选定的文本就是点击的控件的文本,而如果不设置contentEditable为true,则很大概率会选定同页面出现相同文本的第一个地方。
二、保存控件原始属性
/* 现场保存与恢复 */
/*
临时变量, 用于保存需要复制文本的控件的原始状态
*/
var OriginStatus = OriginStatus || { };
/*
功能: 保存控件原始状态
*/
function SaveOriginStatus(oSource) {
//oSource.disabled = 'disabled';//禁用后不能复制
//oSource.readOnly = true;//无效, 还是可以复制
OriginStatus.contentEditable = oSource.contentEditable;
OriginStatus.disabled = oSource.disabled;
}
/*
功能: 还原控件原始状态
*/
function RecoverOriginStatus(oSource) {
oSource.contentEditable = OriginStatus.contentEditable;
oSource.disabled = OriginStatus.disabled;
}
三、鼠标左键按住不放进行控件文本选择
/* 鼠标左键按住不放进行控件文本选择 */
var isBound = false;
document.attachEvent("onmousedown",
function() {
isBound = true;
});
document.attachEvent("onmouseup",
function() {
isBound = false;
});
方法内注册事件用attachEvent,没有考虑到非IE的情况。
四、选中要复制的控件的文本
/*
功能: 选中要复制的控件的文本。
NOTE: 方法内部是选中控件所有文本, 而非部分.
*/
function fnSelectText(oSource, e) {
if (!oSource) return;
e = e || window.event;
e.returnValue = false;
//textarea采用自身选定功能. 注意textarea不能被disabled
if(oSource.type == "textarea") return;
//设置为可编辑, 是为了减少findText方法选中第一个的几率
SaveOriginStatus(oSource);
SetCanCopy(oSource);
var sSourceText = GetControlText(oSource);
var caretPos = sSourceText.length; //文本长度
if (caretPos == 0) return;
if (oSource.createTextRange) {
var r = oSource.createTextRange();
r.move('character', caretPos);
r.select();
} else if (oSource.setSelectionRang) {
oSource.setSelectionRange(caretPos, caretPos);
oSource.focus();
} else {
//TODO: BUG, 如果页面有多个相同文本, 则会选中第一个
var r = document.selection.createRange();//或者document.body.createTextRange();
r.findText(sSourceText);
//动态添加的内容, 可能会导致异常: htmlfile: Could not complete the operation due to error 800a025e.
r.select();
}
RecoverOriginStatus(oSource);
}
注意:方法内部是选中控件所有文本, 而非部分。另外还有个BUG未解决:如果页面有多个相同文本, 则会选中第一个。
五、页面事件注册
//双击控件选定文本事件
document.attachEvent("ondblclick",
function(e) {
//模式窗口下Label控件不属于document.activeElement
if(window.event.srcElement) {
fnSelectText(window.event.srcElement, window.event || e);
}
});
//鼠标左键按住移动选中事件
document.attachEvent("onmouseover",
function(e) {
if(!!isBound) {
if(window.event.srcElement) {
fnSelectText(window.event.srcElement, window.event || e);
}
}
});
//鼠标右键事件
//document.attachEvent("onmousedown", function(e) {
// e = e || window.event;
// //点击鼠标右键
// if(e.button == 2) {
// var oSource = window.event.srcElement;
// if(oSource.type == "textarea") return;
// else {
// //请同时按下Ctrl和C组合键进行复制或者长按鼠标左键将文本拖拉到富文本编辑器中!
// alert("请同时按下Ctrl和C组合键进行复制!");
// //window.event.cancelBubble = true;
// //e.returnValue = false;
// }
// //createCopyTextarea(oSource);
// //window.event.srcElement.contentEditable = true;
// }
//});
document.attachEvent("oncontextmenu", function(e) {
var oSource = window.event.srcElement;
if(oSource.type == "textarea") return;
else {
alert("请同时按下Ctrl和C组合键进行复制!");
}
});
将事件注册到document,而不是某个控件,主要是考虑到页面如果有多个控件的话,逐个控件注册比较麻烦。这样处理也符合用户习惯,鼠标左键选定或者双击选定文本,然后按Ctrl+C组合键复制即可。
六、使用方法
假设脚本文件名为CopyDataOnModalWindow.js,文件存放路径为"http://www.cnblogs.com/Scripts/js/CopyDataOnModalWindow.js",那么可以如下调用:
<script type="text/javascript">
if(window.document.readyState == "interactive") {
if (!window.opener) {
//如果是在模式窗口下, 才引用脚本
var s = document.createElement('script');
s.src = "http://www.cnblogs.com/Scripts/js/CopyDataOnModalWindow.js";
s.type = "text/javascript";
window.document.getElementsByTagName("head")[0].appendChild(s);
} else {
}
}
</script>
注意:我不确定 !window.opener就一定是模式窗口,如果您有判断模式窗口更好的方法,请留言告知。
这段脚本放在页面最后即可。
〇、结束语及遗留问题
脚本如此处理,可以不用污染页面,只需要复制脚本调用方法即可。遗憾的是,没有解决JavaScript操作剪贴板出现异常的问题;也没处理好一些细节。
说明:
1.textarea控件如果不是disabled状态的话,即使是readOnly,是可以选定并且浏览器右键菜单可以弹出,所以处理时排除掉textarea;如果是disabled状态的话,双击、鼠标点击事件均不会被触发,暂时没有想到有什么其他办法可以解决。
2.select控件的文本也无法选定。但select控件disabled状态下事件可以被触发。
3.选定后,无法右键弹出浏览器原生菜单;如果是自定义菜单,暂时无法解决JavaScript操作剪贴板出现异常的问题;
4.细节问题
bug: 选择控件文本, 如果页面有多处相同文本, 将会选中第一个(当然也可以复制到文本)
bug: 选定控件文本, 鼠标左键在选定区域按下后不放, 将文本拖拉到其他地方再释放, 这个时候isBound 还是 true;或者某种情形下,点击右键,移动鼠标会使得鼠标移动过的控件逐个选定文本。这个无关大雅,不过没有深入处理。
----end----
浙公网安备 33010602011771号