/**
*编辑使用区域,
*格式定义:1、行元素为div
* 2、里面样式元素为span元素设置style
* 3、编辑功能点击按钮为button按钮 统一设置样式 padding: 0; background: 0 0; outline: 0; -moz-outline: 0; border: 0; display: block; cursor: pointer; margin: 0;
*/
Namespace.register("U.UF.E");
/* 初始化编辑器,让编辑器的格式符合
*
* @param el {element} 编辑的元素
* @param callback {function} 非必传 操作处理函数
* 操作处理函数 该函数默认第一个参数为操作记录。
* 格式形如 : { updateLine : [ 修改行ID, 修改行ID,], addLine : [添加行ID], deleteLine : [删除行ID] }
* @param content {string} 默认添加的内容
* @param stylestate {function} 非必传 光标所在行样式状态处理
*/
U.UF.E.initEditor = function (el, synergy, content, stylestate) {
//el是编辑器加载到哪个元素下必须传的元素 第二个是编辑器触发的回调函数 第三个是编辑器需要加载的内容 第四个是编辑器内容变化的时候的回调函数
//这个函数主要的逻辑内容是实现编辑器初始化内容,如果内容为空的时候那么初始化首行
//编辑器需要初始化内容的时候
if (content) {
//先加载内容
el.innerHTML = content; //设置内容
el.focus(); //编辑器编辑区域聚焦
//判断加载的内容是否是通过1473编辑器初始化过的内容,如果是没有初始化过的内容,那么重新初始化
if (!$("div", el)[0] || U.selectEl("div", el)[0].id.length != "37") {
el.innerHTML = ""; //清理内容
U.UF.E.textFormat(content, el); //重新加载内容
U.selectEl("div", el)[0].focus(); //聚焦
}
//暂时先注释掉,去除外部引入的内容有包含可编辑元素,还有设置了不可编辑状态,导致文档不能流畅使用
// U.selectEl("textarea", el).remove(); //去除textarea
// U.selectEl("div", el).addAttrArray({ "contentEditable": "" }); //设置可编辑
}
//没有内容的初始化
else {
//创建行元素
var _div = $$("div", { "id": "e" + Guid.newGuid(), "innerHTML": content || "
" }, el); //创建一个编辑的div进行编辑处理
el.focus(); //编辑器编辑区域聚焦
}
//上面处理内容后,下面初始化
U.UF.E.variable(el, synergy, stylestate); //初始化全局变量
//事件监听
U.UF.E.key(el); //键盘监听
//设置样式
U.UF.E.formatBrush(el, false); //格式刷工具未启用状态 记录当前光标所在位置的文字样式
//创建图片拉伸控件
U.UF.E.picture.stretch(el); //加载图片拉伸控件
//得到现在编辑器使用的行
el.idarr = U.UF.E.key.getLineIdArr(el);
//设计前进后退行记录
el.editor.recordOpera = { "line": el.idarr }
return U.UF.E.getRangeAt(); //得到光标
}
/* 初始化编辑器全局变量
*
* @param el {element} 编辑的元素
*/
U.UF.E.variable = function (el, synergy, stylestate) {
var _range = U.UF.E.getRangeAt(); //得到光标
//编辑器全局区域
el.editor = {
"isrecord": true,
"idarr": [], //删除或者添加变化的数组
//格式刷全局变量
"brushStyle": {
"font-family": {},
"font-size": {},
"font-weight": {},
"font-style": {},
"text-decoration": {},
"color": {},
"backgroundColor": {}
},
//外部引入的内容需要保留的对象
"recordRangeStyle": {
"font-family": "",
"font-size": "",
"font-weight": "",
"font-style": "",
"text-decoration": "",
"color": "",
"backgroundColor": ""
},
"styleState": stylestate, //样式状态管理回调
"maxWidth": U.selectEl(el)[0].offsetWidth, //记录最大宽度
"operaNotice": synergy, //设置编辑器处理的回调函数
"recordRange": _range, //当前使用的光标
"recordHTML": "", //当前操作行的内容
"recordOpera": {}, //记录行内容
"dpi": U.UF.CI.getDPI()[0], //获取屏幕分辨率
"log": true, //是否输出日志
"recordsEditor": [], //操作记录数组
"recordsEditorIndex": 0 //当前操作记录位置
};
}
/* 粘贴的处理
*
* @param e {event} 操作对象
* @param editor {element} 编辑器
* @param text {string} 需要处理的文字
*/
U.UF.E.onpaste = function (e, editor, text) {
var _content, event = e || window.event;
if (text != undefined) {
_text = text;
}
else {
_text = U.UF.C.pasteText();
}
_content = _text.SplitAngleBrackets();
if (_content && _content.length < 2) {
//普通文本替换的处理
_text = "
").replace(/ /g, " ");
_text.trim() != "" && U.UF.E.textFormat(_text, editor); //文字格式化处理
U.UF.EV.stopDefault(); //去除默认事件
return _text.trim();
}
/* 粘贴的处理
*
* @param text {string} 需要处理的文字
* @param range {object} 光标对象
*
*/
U.UF.E.textFormat = function (text, editor) {
var _editor = editor || this.editor;
var _range = U.UF.E.getRangeAt(), //获取光标选取
_div = $$("div", { "innerHTML": text, "style": { "display": "none"} }, U.selectEl("body")[0]), //内容
_frag = U.UF.E.unifiedFormat(_div); //获取拆分的值
U.UF.E.insertContent(_frag, _range, _editor); //调用指定位置插入内容的函数
//获取table进行初始化
var _table = U.selectEl('table', _editor);
//表格处理 写在这里
for (var i = _table.length - 1; i >= 0; i--) {
U.UF.E.table.load(_table[i]);
}
U.selectEl(_div).remove(); //删除div元素
}
/* 在指定位置插入内容
*
* @param el {element} 插入的元素 frag临时标签
* @param range {object} 光标对象
*
*/
U.UF.E.insertContent = function (el, range, editor) {
range = range || U.UF.E.getRangeAt(); //获取光标选取
//html5浏览器.此处添加了&& el.textContent会导致论坛上传不了图片,需要再次研究
if (window.getSelection) {
//if (window.getSelection && el.textContent) {
var _i, //循环变量
_frag,
_stylecsstext,
_span,
_child = el.childNodes, //获取插入元素的所有孩子节点
_lastchild, //记录最后一个孩子节点变量
_extractcontent, //记录删除选区内容
_record,
_focusel,
_frag = $$("frag"), //创建frag 临时标签
_startline = range.startContainer == editor ? editor.children[0] : U.UF.E.getLineElement(range.startContainer), //选择的行
_endline = range.endContainer == editor ? editor.children[0] : U.UF.E.getLineElement(range.endContainer), //选择的列
_selection = window.getSelection()//获取选区函数
;
if (editor.innerHTML == "") {
_record = { addLine: [] };
for (_i = 0; _i < _child.length; ) {
_record.addLine.push(_child[_i].id);
//循环把选区内容元素插入到临时标签中
editor.appendChild(_child[_i]);
}
U.UF.E.elementFocus(range, editor.children[0], true); //重新聚焦元素
editor.editor.recordHTML = editor.children[editor.children.length - 1].outerHTML;
}
else {
_record = { updateLine: [_startline.id], addLine: [] };
//移除选取的内容
range.deleteContents(); //移除文字
_selection.removeAllRanges(); //移除选取
//剪切区域移除br标签,反正br导致多次换行
// U.selectEl("br", _startline).remove(); //移除所有的br标签
// U.selectEl("br", _endline).remove(); //移除所有的br标签
_lastchild = _endline.lastChild; //获取结束行最后一个元素
//粘贴的第一行有内容的处理
if (_lastchild && (_lastchild.innerHTML != undefined || _lastchild.data != undefined)) {
_stylecsstext = (_lastchild.style || _lastchild.parentNode.style).cssText; //首行的样式处理
_focusel = _child[_child.length - 1].childNodes[_child[_child.length - 1].childNodes.length - 1] || _child[_child.length - 1]; //剪切后最后聚焦的元素
//结束行是向前插入,先把结束好的文字剪切走
try {
range.setEnd(_lastchild, _lastchild.innerHTML != undefined ? 1 : _lastchild.data.length); //设置光标结束的位置
}
catch (e) {
range.setEnd(_lastchild, 0); //设置光标结束的位置
}
_extractcontent = range.extractContents(); //记录删除选区内容
//把最后一行选取的内容如果是文本那么转化成span标签 _extractcontent.childNodes[0].nodeType == 3 && U.UF.E.validElement(_extractcontent)
if (_extractcontent.childNodes[0] && _extractcontent.childNodes[0].nodeType != 1) {
//重新创建一个新的粘贴信息
_frag = $$("frag");
_span = $$("span", { "style": { "cssText": _stylecsstext} }, _frag);
_span.appendChild(_extractcontent);
_extractcontent = _frag;
}
//如果选取最后一行的内容是div说明是整行的处理
if (_extractcontent.childNodes[0] && _extractcontent.childNodes[0].tagName == "DIV") {
//把行元素所有的元素添加到粘贴元素李
for (_i = 0; _i < _extractcontent.childNodes[0].childNodes.length; _i) {
//样式的设置
_extractcontent.childNodes[0].childNodes[_i].style.cssText = _extractcontent.childNodes[0].style.cssText + ";" + _extractcontent.childNodes[0].childNodes[_i].style.cssText;
_child[_child.length - 1].appendChild(_extractcontent.childNodes[0].childNodes[_i]);
}
}
//否则就是内容
else {
_child[_child.length - 1].appendChild(_extractcontent); //将选区内容元素插入到选区最后一个节点
}
//第一行添加
for (_i = 0; _i < el.childNodes[0].childNodes.length; _i) {
_startline.appendChild(el.childNodes[0].childNodes[_i]); //设置第一行的内容为插入元素的内容
}
}
//否则其他的情况
else if (_child[0]) {
//设置起始行的样式为选区孩子节点的第一个元素的样式
_startline.style.cssText += " " + U.UF.E.getRemainAttr(_child[0]);
//设置起始行的内容为插入元素的第一个孩子节点的内容
_startline.innerHTML = _child[0].innerHTML;
_focusel = _startline;
}
//循环中间行添加处理
for (_i = 1; _i < _child.length; ) {
_record.addLine.push(_child[_i].id);
//循环把选区内容元素插入到临时标签中
_frag.appendChild(_child[_i]);
}
U.selectEl(_startline.parentNode).append(_frag, 0, U.selectEl(_startline).next()[0]); //添加到选择行的后面
U.UF.E.elementFocus(range, _focusel, true); //重新聚焦元素
var _focusline = U.UF.E.getLineElement(_focusel);
if (_focusline != _startline) {
editor.editor.recordRange = range;
}
editor.editor.recordHTML = _focusline.outerHTML;
}
U.UF.E.operationNotice(_record, editor);
clearTimeout(editor.editor.interval); //取消计时更新
}
//低版本的ie兼容
else {
range.pasteHTML(el.outerHTML); //添加选取文字
}
};
/* 元素全选聚焦
*
* @param range {object} range光标对象
* @param el {element} 编辑的元素
*
*/
U.UF.E.elementFocus = function (range, el, islast) {
//html5得到光标的处理
if (window.getSelection) {
var _selection = window.getSelection(); //选择选取的处理
range.selectNodeContents(el); //添加选取的光标
_selection.removeAllRanges(); //移除所有的光标
_selection.addRange(range); //把聚焦元素的光标添加进去
//判断光标是否放在最后面
if (islast) {
range.collapse(false);
}
}
//ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
else {
range.moveToElementText(el); //光标移动到指定的元素位置
range.select(); //聚焦选择
}
};
/* 创建贯标
*
*
*/
U.UF.E.createRnage = function () {
//html5得到光标的处理
if (window.getSelection) {
return document.createRange();
}
//ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
else {
return document.body.createTextRange();
}
}
/* 初始化光标处理,要求光标必须聚焦到编辑区域里,否则这里获取就会失败
*
* @param win {window} 编辑的域
* @return {object} 光标编辑对象
*
*/
U.UF.E.getRangeAt = function (win) {
var _selection, //选取对象
_range //光标对象
;
win = win || window; //获取创建光标的域
//html5得到光标的处理
if (win.getSelection) {
_selection = win.getSelection(); //获取选取对象
//当获取选取中有光标的处理
if (_selection.rangeCount) {
_range = _selection.getRangeAt(0); //返回选区的处理
}
}
//ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
else {
_selection = win.document.selection; //获取选取对象
_range = _selection.createRange(); //光标对象
}
return _range; //光标的处理
};
/* 替换选区内容处理,可添加元素html代码。
*
* @param str {string} 需要插入的文字
* @param range {object} range光标对象
* @param islast {boolean} 是否聚焦到最后
* @return {object} 光标编辑对象
*/
U.UF.E.addRange = function (str, range, islast) {
range = range || U.UF.E.getRangeAt(); //获取光标处理
//html5得到光标的处理
if (window.getSelection) {
var _selection = window.getSelection(), //获取选取对象
_frag = range.createContextualFragment(str); //创建选取
range.deleteContents(); //移除文字
_selection.removeAllRanges(); //移除选取
range.insertNode(_frag); //插入需要写入的内容
//判断光标是否放在最后面
if (islast) {
range.collapse(false);
}
_selection.addRange(range); //把替换的文章添加到当前指定的选取中
}
//ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
else {
range.select(); //选取聚焦
range.pasteHTML(str); //添加选取文字
//判断光标是否放在最后面
if (islast) {
range.collapse(false);
}
}
//上面重新操作光标后,需要重新聚焦
return U.UF.E.getRangeAt();
};
/* 在光标中获取现在聚焦的元素
*
* @param range {object} range光标对象
*/
U.UF.E.getRangeElement = function (range) {
//html5得到光标的处理
if (range.commonAncestorContainer) {
return range.commonAncestorContainer;
}
//ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
else {
//正常选择元素获取元素的处理
if (range.parentElement) {
return range.parentElement();
}
//图片无法像上面的方法一样获取元素,需要通过commonParentElement获取元素
else {
return range.commonParentElement();
}
}
};
/* 重新选中指定的光标
*
* @param range {object} range光标对象
*/
U.UF.E.reSelectRange = function (range) {
//html5得到光标的处理
if (window.getSelection) {
var _selection = window.getSelection(); //获取选取对象
_selection.removeAllRanges(); //移除选取
_selection.addRange(range); //光标重新聚焦处理
}
//ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
else {
range.select(); //选取聚焦
}
};
/* 设置编辑样式
*
* @param attr {object} 给指定的光标设置样式
* @param range {object} 非必传参数 range光标对象
* */
U.UF.E.setRangeStyle = function (attr, range, editor) {
range = range || U.UF.E.getRangeAt(); //获取光标处理
if (range.startContainer == range.endContainer && range.startOffset == range.endOffset) {
return true;
}
var _i, //循环变量定义
_textstyle, //记录文本样式
_isdel, //是否删除
_start = range.startContainer, //选区起始元素
_end = range.endContainer, //选区结束元素
_startoffset = range.startOffset, //开始位置
_endoffset = range.endOffset, //结束位置
_startline = U.UF.E.getLineElement(_start), //获取选区起始行元素
_endline = U.UF.E.getLineElement(_end), //获取选区结束行元素
_frag = $$("frag") //创建临时元素 用于做记录d
;
editor = editor || _startline.parentNode; //编辑区域元素
if (!editor.editor) { return; }
var _record = U.UF.E.getUpdateLine(_startline, _endline, editor); //得到修改记录
//判断是否选区在同一行
if (_startline != _endline) {
//不同行处理
var _rangselect = range.extractContents().childNodes; //获取选区的所有元素
//记录新选区的起始元素
_start = _rangselect[0].childNodes[0];
//记录文字装饰样式
_textstyle = attr["text-decoration"] || attr["textDecoration"];
//第一行样式设置
U.UF.E.setStyle(attr, _rangselect[0], true);
if (attr.cssText == "") {
_startline.style.cssText = "";
}
//设置样式后的元素循环添加到第一行中
while (_rangselect[0].childNodes[0]) {
_startline.appendChild(_rangselect[0].childNodes[0]);
}
//如果存在文字装饰样式
if (_textstyle) {
//标记设置的样式中是否已存在 存在为1 不存在为 0
_isdel = (attr["text-decoration"] || attr["textDecoration"] || "").indexOf(_textstyle) > -1 ? 1 : 0;
attr["text-decoration"] = _textstyle;
}
//循环除第一行和最后一行的每一行的处理
for (_i = 1; _i < _rangselect.length - 1; ) {
//设置每一行的样式
U.UF.E.setStyle(attr, _rangselect[_i], _isdel);
if (_textstyle) {
attr["text-decoration"] = _textstyle;
}
if (attr.cssText == "") {
_rangselect[_i].style.cssText = "";
}
//追加到临时标签中
_frag.appendChild(_rangselect[_i]);
}
//最后一行样式设置
U.UF.E.setStyle(attr, _rangselect[_rangselect.length - 1], _isdel);
//获取选区最后一行元素
var _end = _rangselect[_rangselect.length - 1].childNodes[_rangselect[_rangselect.length - 1].childNodes.length - 1];
//设置样式后的元素循环添加到最后一行中
while (_rangselect[_rangselect.length - 1].childNodes[0]) {
U.selectEl(_endline).append(_rangselect[_rangselect.length - 1].childNodes[_rangselect[_rangselect.length - 1].childNodes.length - 1], 0, _endline.firstChild);
}
if (attr.cssText == "") {
_endline.style.cssText = "";
}
range.insertNode(_frag); //插入需要写入的内容
U.UF.E.setRange(_start, _end || _start, 0, 1, range); //设置选区 重新聚焦
}
//同行处理
//同行且选择的父级为块级元素
else if (_start == _end && (_start.parentNode.tagName.toLowerCase() == "span" || _start.parentNode.tagName.toLowerCase() == "a")) {
var _parentspan = _start.parentNode; //获取起始标签的上级元素
var _tagname = _parentspan.tagName.toLowerCase() == "a" ? "a" : "span"; //判断创建的块级元素TagName
var _startsplitel = U.UF.E.splitText(_start, _startoffset); //将起始标签拆分成新的起始文本标签 返回剩余的标签
var _endsplitel = U.UF.E.splitText(_startsplitel, _endoffset - _startoffset); //在剩余标签中拆分成选中和结束两块文本标签
//如果第一个文本标签存在内容则创建新的span标签
if (_start.data) {
//创建新的span标签 该标签为起始span标签(选区前的span标签)
var _span = $$(_tagname, {
"style": { "cssText": U.UF.E.getRemainAttr(_parentspan) },
"innerHTML": _start.data
});
//如果为a标签则设置href属性
if (_tagname == "a") {
_span.href = _parentspan.href;
}
//替换起始文本标签为起始span标签
_parentspan.replaceChild(_span, _start);
}
//创建新的块级元素 该标签为选区的span标签
var _rangspan = $$(_tagname, {
"style": { "cssText": U.UF.E.getRemainAttr(_parentspan) },
"innerHTML": _startsplitel.data
});
//处理样式后进行设置块级元素中
U.selectEl(_rangspan).css(U.UF.E.setSpecialAttr(_rangspan, attr));
//如果为a标签则设置href属性
if (_tagname == "a") {
_rangspan.href = _parentspan.href;
}
//替换选区文本标签为选区span标签
_parentspan.replaceChild(_rangspan, _startsplitel);
//如果结束文本标签存在内容则创建新的span标签
if (_endsplitel.data) {
//创建新的span标签 该标签为结束span标签(选区后的span标签)
var _span1 = $$(_tagname, {
"style": { "cssText": U.UF.E.getRemainAttr(_parentspan) },
"innerHTML": _endsplitel.data
});
//如果为a标签则设置href属性
if (_tagname == "a") {
_span1.href = _parentspan.href;
}
//替换结束文本标签为结束span标签
_parentspan.replaceChild(_span1, _endsplitel);
}
//将替换的元素追加到临时元素中
for (i = 0; i < _parentspan.childNodes.length; ) {
_frag.appendChild(_parentspan.childNodes[i]);
}
//替换原有元素为修改的元素
_parentspan.parentNode.replaceChild(_frag, _parentspan);
//设置选区
U.UF.E.setRange(_rangspan, _rangspan, 0, _startsplitel.data ? 1 : 0, range);
}
//起始元素和结束元素相等 且本身就为块级元素的处理
else if (_end == _start && _start.tagName && (_start.tagName.toLowerCase() == "span" || _start.tagName.toLowerCase() == "a")) {
//记录原有的样式属性
U.UF.E.getRemainAttr(_start);
//处理样式后设置到起始元素中
U.selectEl(_start).css(U.UF.E.setSpecialAttr(_start, attr));
}
//当行跨元素
else {
var _rangselect = range.extractContents(); //获取选区的所有元素
U.UF.E.setStyle(attr, _rangselect, true); //直接调用设置样式函数 true表示为第一层
range.insertNode(_rangselect); //将设置的元素插入到光标位置
}
//获取修改行的信息处理
U.UF.E.operationNotice(_record, editor);
};
/* 设置样式
*
* @param startline {element} 修改样式修改行
* @param endline {element} 修改样式结束行
*/
U.UF.E.getUpdateLine = function (startline, endline, edit) {
var _record = { updateLine: [] }; //记录
//循环找所有影响的行
while (startline) {
_record.updateLine.push(startline.id); //修改行记录
//向下寻找
if (startline != endline) {
startline = startline.nextElementSibling;
}
else {
startline = false;
}
}
//返回修改记录
return _record;
};
/* 设置样式
*
* @param attr {object} 给指定的光标设置样式
* @param el {object} 设置样式的元素
* @param istop {boolean} 是否为第一层标记
*/
U.UF.E.setStyle = function (attr, el, istop) {
var _nowattr, //记录当前属性 该变量的作用主要用于记录新的样式
_nowspan, //记录当前元素的span元素
_newspan, //记录新的span元素
_textstyle = attr["text-decoration"] || attr["textDecoration"],
_span = U.UF.E.getTagNameElement(el); //获取块级元素
var _spanText = _span && _span.innerHTML; //获取行级元素的innerHTML
//根据内容是否相等 判断是否选择整个span标签
if (_span && _spanText == el.data) {
_nowattr = U.UF.E.setSpecialAttr(_span, attr); //整理特殊样式
U.selectEl(_span).css(_nowattr); //设置样式
}
//如果设置样式的元素不为整个span标签
else {
var _rangselect = el.childNodes; //获取设置样式元素下的所有子级
//循环给每一个子级添加样式
for (var i = 0; i < _rangselect.length; i++) {
//是第一层且为第一个元素是处理样式
if (istop === true && !i) {
U.UF.E.setSpecialAttr(_rangselect[i], attr); //设置最后需要设置的值
//设置istop 设置后的功能为判断是否需要设置
istop = (attr["text-decoration"] || attr["textDecoration"] || "").indexOf(_textstyle) > -1 ? 1 : 0;
}
//如果存在文字装饰属性
if (attr["text-decoration"] || attr["textDecoration"]) {
//需要添加样式的处理
if (istop === 1) {
//如果为元素节点且存在文字装饰属性 并且不等于inherit和node
if (_rangselect[i].style && _rangselect[i].style["text-decoration"] && _rangselect[i].style["text-decoration"] != "inherit" && _rangselect[i].style["text-decoration"] != "none") {
//修改设置的属性为原有样式加当前样式
attr["text-decoration"] = _rangselect[i].style["text-decoration"].replace(_textstyle, "") + " " + _textstyle;
}
//否则则直接设置为当前样式
else {
attr["text-decoration"] = _textstyle;
}
}
//需要删除的处理
else if (istop === 0) {
//判断是否为元素节点
//如果是元素节点
if (_rangselect[i].style) {
//判断是否存在当前样式
//如果存在则去除当前样式
if (_rangselect[i].style["text-decoration"].indexOf(_textstyle) > -1) {
//去除当前样式
attr["text-decoration"] = _rangselect[i].style["text-decoration"].replace(_textstyle, "");
//去除完毕后如果为空则设置为inherit
if (attr["text-decoration"] == "") {
attr["text-decoration"] = "inherit";
}
}
//不存在时直接替换
else {
attr["text-decoration"] = _rangselect[i].style["text-decoration"];
}
}
//否则直接设置为inherit(继承父级属性)
else {
attr["text-decoration"] = "inherit";
}
}
}
//根据是否存在tagName(标签名) 判断是否为元素节点
//如果为元素节点则直接设置样式
if (_rangselect[i].tagName) {
U.selectEl(_rangselect[i]).css(attr); //设置样式
}
//否则则创建新的span标签 并替换原有是元素
else if (_rangselect[i].nodeValue) {
//创建新的span标签
_newspan = $$("span", {
"innerHTML": _rangselect[i].nodeValue,
"style": attr
});
//替换原有是元素
_rangselect[i].parentNode.replaceChild(_newspan, _rangselect[i]);
}
}
}
};
/* 特殊样式处理
*
* @param element {element} 被继承样式的元素
* @param attr {object} 当前的样式属性
*/
U.UF.E.setSpecialAttr = function (element, attr) {
var _key, //for in 循环的key值
_newvalue, //新的值
_value; //当前值
if (element.style) {
//循环没个样式
for (_key in attr) {
if (attr[_key] == "") {
attr[_key] = "";
}
else {
//判断是否为文字装饰样式属性
if (_key == "text-decoration" || _key == "textDecoration") {
//获取当前元素该样式的值
_value = element.style[_key];
//获取的样式有值且不为继承属性时
if (_value && _value != "inherit" && _value != 'none') {
//删除样式中的属性
_newvalue = _value.replace(attr[_key], "");
//如果替换后为空则设置为继承
if (_newvalue == "") {
attr[_key] = "inherit";
}
//否则如果替换后的值相等则将值设置进去
else if (_newvalue == _value) {
attr[_key] = attr[_key] + " " + _value;
}
//如果不等于则设置为新的值
else {
attr[_key] = _newvalue;
}
}
}
//否则如果设置的样式等于原本的样式 则设置为继承属性
else if (attr[_key] == element.style[_key] && "font-weight|fontWeight|font-style|fontStyle|".indexOf(_key) > -1) {
attr[_key] = "inherit";
}
}
}
}
//返回处理好后的属性
return attr;
};
/* 把一个text标签进行拆分
*
* @param node {element} 元素节点
* @param offset {number} 拆分的位置
*/
U.UF.E.splitText = function (node, offset) {
//如果拆分文字的位置等于总的长度,那么就在最后面添加空文本。
if (offset == node.nodeValue.length) {
var next = document.createTextNode('');
U.selectEl(node.parentNode).append(next, null, node);
return next;
}
var retval = node.splitText(offset);
return retval;
};
/* 获取到行元素
*
* @param el {element} 选取元素
*/
U.UF.E.getLineElement = function (el) {
var _mel = el,
_tagname = el.tagName ? el.tagName.toLowerCase() : ""; //获取元素的标签名
//循环得到行元素
while (el && _tagname != "body" && (_tagname != "div" || !(el.id && el.id.length == "37"))) {
el = el.parentNode;
if (el) {
_tagname = el.tagName ? el.tagName.toLowerCase() : ""; //标签名
}
};
return (el && el.id) ? el : null;
};
/* 获取到块级元素
*
* @param {element} 选取元素
*/
U.UF.E.getTagNameElement = function (node, tagname) {
tagname = tagname || 'span';
while (node) {
if (node.nodeName.toLocaleLowerCase() === tagname) {
return node;
} else if (node.nodeName.toLocaleLowerCase() === 'div' && !node.inline) {
return null;
}
node = node.parentNode;
}
};
/* 设置行的样式,如居中,局左,局右,设置编号等等功能
*
* @param {object} range光标对象
* @param {object} 给指定的光标设置样式
*/
U.UF.E.setLineStyle = function (style, range) {
if ($('.U_UF_E_Picture_dragDot')[0]) {//清除图片拉伸的的虚拟框
U.selectEl('.U_UF_E_Picture_dragDot')[0].style.display = "none";
}
range = range || U.UF.E.getRangeAt(); //获取光标处理
var _rangeline,
_start = range.startContainer
_td = U.selectEl(_start).Parent({ "tagName": "TD" }); //起始选区
//判断居中的元素是不是td标签
if (_td && _td.tagName == "TD") {
_rangeline = [_td];
}
else {
_rangeline = U.UF.E.getRangeLineElement(range);
}
var i = 0; //设置循环变量
for (i = 0; i < _rangeline.length; i++) { //循环设置样式
U.selectEl(_rangeline[i]).css(style); //设置样式
}
U.UF.E.reSelectRange(range);
return range; //返回选区对象
};
/* 获取选区行元素
*
* @param range {object} range光标对象
* */
U.UF.E.getRangeLineElement = function (range) {
range = range || U.UF.E.getRangeAt(); //获取光标处理
var _start = range.startContainer, //起始选区
_end = range.endContainer, //结束选区
_stratline = U.UF.E.getLineElement(_start), //起始选行
_endline = U.UF.E.getLineElement(_end), //结束选行
_nextline = U.selectEl(_stratline).next()[0], //下一行
_rangeline = [_stratline]; //选中行记录
if (_stratline != _endline) { //如果起始行不等于结束行则证明选择多行
while (_nextline) { //循环记录选择的每一行
_rangeline.push(_nextline); //添加到选择行记录中
if (_nextline != _endline) { //如果依旧不等于结束行 则证明未获取完毕
_nextline = U.selectEl(_nextline).next()[0]; //修改下一行变量
} else { //直至等于为止
_nextline = false;
}
}
}
return _rangeline;
}
/* 设置字体方向
*
* @param direction {string} 方向 left center right
* */
U.UF.E.textAlign = function (direction) {
U.UF.E.setLineStyle({ 'text-align': direction });
};
/* 设置光标位置
*
* @param {element} 选区起始元素
* @param {element} 选区结束元素
* @param {number} 起始位置
* @param {number} 结束位置
* @param {number} 光标对象
*/
U.UF.E.setRange = function (startel, endel, start, end, range) {
range = range || U.UF.E.getRangeAt(); //获取光标处理
//html5处理光标选取的处理
if (window.getSelection) {
//判断光标没有聚焦到制定的元素上,就无法设置焦点,这里需要处理聚焦问题。
if (startel == endel && range.startContainer != startel) {
range.selectNodeContents(startel); //由于位置要还原制定span标签中
}
range.setStart(startel, start); //设置光标开始的位置
range.setEnd(endel, end); //设置光标结束的位置
}
//ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
else {
var _range1 = document.body.createTextRange(), //创建一个光标1
_range2 = document.body.createTextRange(); //创建一个光标2
_range1.moveToElementText(startel); //光标放在开始的地方
_range1.moveStart("character", startel); //给光标设置
_range2.moveToElementText(endel); //光标放在结束的地方
_range2.moveStart("character", end); //设置光标结束区域的位置
_range1.setEndPoint("EndToStart", _range2); //光标1和光标2接连在一起形成选取
_range1.select(); //选择
range = _range1;
}
return range;
}
/* 格式整理,只整理第一层和第二层
*
* @param el {element} 整理的内容元素
*/
U.UF.E.unifiedFormat = function (el) {
var _i, //循环
_float,
_tagname,
_removeTagName = ['head', 'meta', 'script', 'link', 'style', 'title'], //需要移除的的标签
_frag = $$("frag"), //创建临时记录内容标签
_div, //行
_child = el.childNodes; //获取子级,改子级全部为行
//清除多余的元素
U.UF.E.unifiedFormat.remove(el);
//循环处理每一行
for (_i = 0; _i < _child.length; _i++) {
_display = _child[_i].currentStyle ? _child[_i].currentStyle.display : ""; //是否为行标签的处理
_tagname = _child[_i].tagName ? _child[_i].tagName.toLowerCase() : ""; //标签名
_float = _child[_i].currentStyle ? _child[_i].currentStyle.float : ""; //是否为行标签的处理
//附件不进行过滤
if (_child[_i].className == "U_MD_O_attachment") {
U.selectEl(_child[_i]).appendTo(_frag);
continue;
}
//行元素的处理
if (!_div || (_display != "" && _display != "inline") && (_float != "left" || _float != "right")) {
//所有的行标签的处理
//创建行标签
_div = $$("div", { "id": "e" + Guid.newGuid(), "style": { "cssText": U.UF.E.getRemainAttr(_child[_i])} }, _frag);
}
//调用非行元素处理函数 即不为第一层的处理
U.UF.E.unifiedFormat.next(_child[_i], true, _div);
if (!_div.childNodes.length && _frag.childNodes.length > 1) {
U.selectEl(_div).remove();
}
}
//返回处理后的临时元素
return _frag;
};
/* 格式整理,过滤标签
*
* @param el {element} 整理的内容元素
*/
U.UF.E.unifiedFormat.remove = function (el) {
var _i, //循环
_tagname, //标题名
_removeTagName = ['head', 'meta', 'script', 'link', 'style', 'title'], //需要移除的的标签
_child = el.childNodes; //获取子级,改子级全部为行
//循环处理每一行
for (_i = 0; _i < _child.length; _i++) {
_tagname = _child[_i].tagName ? _child[_i].tagName.toLowerCase() : ""; //标签名
//过去注释标签 nodeType为8 则为注释标签
if (_child[_i].nodeType === 8 || (_child[_i].nodeType == 3 && _child[_i].data.trim() == "")) {
_child[_i].remove();
_i--;
continue;
}
//删除过滤的标签
if (_removeTagName.indexOf(_tagname) >= 0) {
U.selectEl(_child[_i]).remove();
_i--;
continue;
}
}
}
/* 非第一行之后的所有内容处理
*
* @param el {element} 处理的元素
* @param top {boolean} 是否为第二层标记 如果为第二层则所有标签直接修改为span标签 否则需要进行拆分
* @return 处理后的结果集
* */
U.UF.E.unifiedFormat.next = function (el, top, fragel) {
var _i, _j, //循环变量
_float,
_display, //记录元素真实的display属性 用于判断是否为行级元素
_tagname, //记录元素的tagName
_nowspan, //记录当前span
_tdchild, //用于子级
_fraga = $$("frag"),
_frag = fragel, //$$("frag"), //用于记录整理后的内容的临时标签
_span, //用于记录块级整理后的内容
_childcsstext, //用于记录获取到的自己的样式
_child = el.childNodes, //获取处理元素子级
_tagname = el.tagName ? el.tagName.toLowerCase() : "",
_cssText = (top.style ? top.style.cssText : "") + ";" + fragel.style.cssText + (_tagname == "img" ? "" : U.UF.E.getRemainAttr(el)); //获取处理元素的样式 用户继承当前样式使用
//清除多余的元素
U.UF.E.unifiedFormat.remove(el);
//如果存在子级的处理
if (_child.length) {
//循环处理每一个子级
for (_i = 0; _i < _child.length; _i++) {
_span = null; //循环重新赋值
//整理当前元素需继承的样式 父级样式 + 当前元素原有样式
_childcsstext = _cssText + ";" + (_child[_i].tagName == "IMG" ? "" : U.UF.E.getRemainAttr(_child[_i]));
_display = _child[_i].currentStyle ? _child[_i].currentStyle.display : ""; //是否为行标签的处理
_float = _child[_i].currentStyle ? _child[_i].currentStyle.float : ""; //是否为行标签的处理
//特殊标签添加样式
//加粗
if (_tagname == "b") {
_childcsstext += ";font-weight: bold;";
}
//斜体
else if (_tagname == "i") {
_childcsstext += ";font-style: italic;";
}
//下划线
else if (_tagname == "u") {
_childcsstext += ";text-decoration: underline;";
}
//删除线
else if (_tagname == "s") {
_childcsstext += ";text-decoration: line-through;";
}
//如果是附件的处理
if (el.className == "U_MD_O_attachment_wrapper") {
}
//如果当前标签为a标签或者top为字符串(当top为字符串时表明存在href属性需要替换为a标签)
else if (_tagname == "a" || (U.UF.C.isElement(top) && top.tagName == "A")) {
//重新设置top值
// top = U.UF.C.isString(top) ? top : el.href;
//设置name属性 用于传递使用
_child[_i].name = _child[_i].name || top.name || el.name || "";
//设置href属性 用于传递使用
_child[_i].href = _child[_i].href || top.href || el.href;
//创建a标签 并设置属性
_span = $$("a", {
"name": _child[_i].name,
"href": _child[_i].href || "javascript:void(0)",
"style": { "cssText": _childcsstext }
}, _fraga);
}
//style样式标签处理
else if (_tagname == "style") {
el = U.selectEl(el).clone(true); //克隆style标签
el.appendTo(_frag); //天机到临时记录标签中
//创建新的行
arguments[2] = _frag = fragel = $$("div", {
"id": "e" + Guid.newGuid(),
"style": { "cssText": _childcsstext }
}, fragel.parentNode);
break; //终止整个循环
}
//table表格标签处理 表格固定为行标签
else if (_tagname == "table") {
if (_frag.innerHTML) {
//创建新的行标签
_span = $$("div", {
"id": "e" + Guid.newGuid(),
"style": { "cssText": _childcsstext }
}, fragel.parentNode);
}
else {
_span = _frag;
}
//克隆当前表格元素
el = U.selectEl(el).clone(true);
//将表格添加到行中
el.appendTo(_span);
//获取所有td节点
_tdchild = U.selectEl("td", el[0]);
//循环保存td节点的内容 过滤表格内的样式
for (_j = 0; _j < _tdchild.length; _j++) {
_tdchild[_j].innerHTML = _tdchild[_j].innerText;
}
//创建新的行
arguments[2] = _frag = fragel = $$("div", {
"id": "e" + Guid.newGuid(),
"style": { "cssText": _childcsstext }
}, fragel.parentNode);
break; //终止整个循环
}
//行元素的处理
else if ((_display != "" && _display != "inline") && (_float != "left" || _float != "right") && _child[_i].innerHTML.trim() != "") {
if (_frag.innerHTML) {
//创建新的行
arguments[2] = _frag = fragel = $$("div", {
"id": "e" + Guid.newGuid(),
"style": { "cssText": _childcsstext }
}, fragel.parentNode);
}
else {
fragel.style.cssText += _childcsstext;
}
}
//否则则为块级元素
else {
_span = $$("span", { "style": { "cssText": _childcsstext} }, _fraga);
}
//进入判断是否依然存在子级 直到处理所有元素为止
var _nowspan = U.UF.E.unifiedFormat.next(_child[_i], _span || top, fragel);
//如果span元素的处理,说明下面只有文本元素的处理
if (_span) {
if (_nowspan.children.length) {
//替换记录标签中的块级标签元素
_fraga.replaceChild(_nowspan, _span);
_frag.appendChild(_fraga);
}
//如果有下级元素的处理
else if (_nowspan.childNodes.length) {
_span.appendChild(_nowspan);
_frag.appendChild(_fraga);
}
else {
U.selectEl(_span).remove();
}
}
else if (_nowspan) {
//替换记录标签中的块级标签元素
_fraga.appendChild(_nowspan);
_frag.appendChild(_fraga);
}
}
}
//如果不存在子级的处理
else {
//是否为第二层标记
if (top == true) {
if (_tagname == "img") {
var _img = U.selectEl(el).clone(true)[0];
_img.style.maxWidth = "100%";
_img.onerror = function () {
this.src = "/img/editorError.png";
this.width = 150;
this.height = 112;
}
_span = $$("span", {
"style": { "cssText": top.style.cssText }, //继承处理元素的样式
//判断是否为a标签如果是则将a标签直接记录 不是则获取内容 !!!!!!!!!注释有问题
"innerHTML": el.innerHTML != null ? el.innerHTML : el.data
});
_span.appendChild(_img);
_frag.appendChild(_span);
}
else {
//如果是则直接创建span块级标签,并添加到记录标签中
$$("span", {
"style": { "cssText": _cssText }, //继承处理元素的样式
//判断是否为a标签如果是则将a标签直接记录 不是则获取内容
"innerHTML": el.innerHTML != null ? el.innerHTML : el.data
}, _frag);
}
}
//如果不为第二层标记
else {
//且存在内容则直接创建文本节点,并添加到记录标签中
if (el.data) {
_fraga.appendChild(document.createTextNode(el.data));
}
//否则则直接克隆该元素,并添加到记录标签中 不做处理 该情况出现在img标签
else if (_tagname == "img") {
var _img = U.selectEl(el).clone(true)[0];
_img.style.maxWidth = "100%";
_img.onerror = function () {
this.src = "/img/editorError.png";
this.width = 150;
this.height = 112;
}
_span = $$("span", {
"style": { "cssText": top.style.cssText }, //继承处理元素的样式
//判断是否为a标签如果是则将a标签直接记录 不是则获取内容
"innerHTML": el.innerHTML != null ? el.innerHTML : el.data
});
_span.appendChild(_img);
_fraga.appendChild(_span);
}
}
}
//返回处理后的元素集合
return _fraga;
};
/* 获取指定的css元素 暂无使用
*
* @param ele {element} 被获取的元素
* */
U.UF.E.getRemainAttr = function (ele) {
//如果存在不存在样式 则返回空
if (!ele || !ele.style) {
return '';
}
//需要删除的属性
var _removeattr = ['position', 'width', 'height', 'background-image', 'border', 'min-height', 'float', 'min-width', 'display', 'padding', 'margin']; //
var _i; //循环变量定义
//循环将需要删除的属性的值设置为空
for (_i = 0; _i < _removeattr.length; _i++) {
//设置为空
ele.style[_removeattr[_i]] = "";
}
//返回设置后的样式
return ele.style.cssText;
};
/* 清除格式
*
* @param range {object} range光标对象
* */
U.UF.E.clearStyle = function (range) {
range = range || U.UF.E.getRangeAt(); //获取光标
var _start = range.startContainer, //选区起始元素
_end = range.endContainer, //选区结束元素
_startline = U.UF.E.getLineElement(_start), //获取选区起始行元素
_endline = U.UF.E.getLineElement(_end); //获取选区结束行元素
//同行相同的样式
if (_startline == _endline && range.toString() == _startline.innerText) {
for (var i = 0; i < _startline.childNodes.length; i++) {
if (_startline.childNodes[i].nodeName !== "#text") {
_startline.childNodes[i].style.cssText = "font-family: 微软雅黑; font-weight: normal; font-size: 10.5pt; line-height: 2;";
}
}
} else {
U.UF.E.setRangeStyle({ "cssText": "" }, range); //设置清空样式
}
U.UF.E.reSelectRange(range);
};
/* 添加超链接
*
* @param el {object} a标签对象
* @param range {object} range光标对象
* */
U.UF.E.addHref = function (el, range) {
U.selectEl("#U_UF_E_herfAlert").remove();
range = range || U.UF.E.getRangeAt(); //获取光标
var _start = range.startContainer, //获取选区起始元素
_end = range.endContainer, //获取选区结束元素
_selectel = range.cloneContents(), //获取选区的所有元素
_startline = U.UF.E.getLineElement(_start), //获取选区起始行元素
_endline = U.UF.E.getLineElement(_end); //获取选区结束行元素
el = el || U.UF.E.getTagNameElement(range.startContainer, "a");
//判断是否跨行选择
if (_startline !== _endline || U.selectEl('img', _selectel)[0]) {
//如果是则提示无法添加A标签
U.UF.UI.alertClick('选择范围横跨多个段落或存在图片,因此无法编辑');
} else {
var _box = $$('div'); //创建Confirm最大层div
if (el) {//判断是否有el
_text = el.innerHTML; //获取文本
_href = el.href; //获取超链接
var _textinput = $$('div', { innerHTML: '
文本 ', "style": { "line-height": "25px", "margin": "40px 41px 17px"} }, _box); //创建文本区域
var _hrefinput = $$('div', { innerHTML: '
链接 ', "style": { "margin": "0px 41px 27px", "line-height": "25px"} }, _box); //创建链接区域
U.UF.UI.confirm(_box, U.UF.C.closure(U.UF.E.addHref.confirm, [range, _hrefinput, _textinput, _text, el])); //创建Confirm
} else {
//否则执行添加A标签操作
_a = U.selectEl('a', _selectel)[0], //获取选区中的第一个a标签
_href = _a ? _a.href : '', //如果存在则已第一个a标签做为href
_text = range.toString(); //获取选区的文字
var _textinput = $$('div', { innerHTML: '
文本 ', "style": { "line-height": "25px", "margin": "40px 41px 17px"} }, _box); //创建文本区域
var _hrefinput = $$('div', { innerHTML: '
链接 ', "style": { "margin": "0px 41px 27px", "line-height": "25px"} }, _box); //创建链接区域
U.UF.UI.confirm(_box, U.UF.C.closure(U.UF.E.addHref.confirm, [range, _hrefinput, _textinput, _text])); //创建Confirm
}
}
};
/**
* Excel确定添加A标签
* @param _cellList 为选中的单元集合
* @param hrefinput {element} 链接区域元素
* @param textinput {element} 文本区域元素
* @param text {string} 选区文本记录
*/
U.UF.E.addHref.excelConfirm = function (_cellList, hrefinput, textinput, text) {
href = U.selectEl('input', hrefinput)[0].value; //获取输入的href
if (U.UF.S.Url.test(href)) { //判断链接是否合理
var _newtext = U.selectEl('input', textinput)[0].value; //获取当前文本
//被修改则直接删除选区 创建a标签直接添加
if (_cellList[0]) {
$$('a', { href: href, innerHTML: _newtext, target: "_blank" }, _cellList[0]); //创建A标签
_cellList[0].removeChild(_cellList[0].children[0]); //删除原来的文本,由创建的A标签代替
} else {
$$('a', { href: href, innerHTML: _newtext, target: "_blank" }, _cellList[0]); //创建A标签
}
}
else {
//提示链接存在有误
U.alert('输入的链接有误,无法添加');
}
};
/**
* 确定添加A标签
* @param range {object} range光标对象
* @param hrefinput {element} 链接区域元素
* @param textinput {element} 文本区域元素
* @param text {string} 选区文本记录
* @param el {object} a标签对象
*/
U.UF.E.addHref.confirm = function (range, hrefinput, textinput, text, el) {
href = U.selectEl('input', hrefinput)[0].value; //获取输入的href
if (new RegExp(/http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/).test(href)) { //判断链接是否合理
var _newtext = U.selectEl('input', textinput)[0].value; //获取当前文本
var _start = range.startContainer, //获取选区起始元素
_end = range.endContainer, //获取选区起始元素
_startspan = U.UF.E.getTagNameElement(_start, 'span'),
_endspan = U.UF.E.getTagNameElement(_end, 'span');
if (el) {//判断是否有el参数(修改)
el.innerHTML = _newtext; //替换文本
el.href = href; //替换超链接
} else {
var _frag = $$('frag');
if (_newtext !== text) { //判断文本是否被修改
//被修改则直接删除选区 创建a标签直接添加
_frag = $$('a', { href: href, innerHTML: _newtext, target: "_blank" }); //创建A标签
} else {
var _selectel = range.extractContents(), //获取选区的所有元素
_rangselect = _selectel.childNodes; //获取选区的子级
var _text = _rangselect.innerHTML || _rangselect.data;
if (_newtext.trim() == "") {
$$('a', { href: href, innerHTML: href, style: { cssText: _startspan.style.cssText }, target: "_blank" }, _frag); //创建A标签
} else {
var i, _csstext;
//循环处理每一个元素
for (i = 0; i < _rangselect.length; i++) {
if (_rangselect[i].nodeType == 3) {
_csstext = i == _rangselect.length ? U.UF.E.getTagNameElement(_startspan, 'span').style.cssText : U.UF.E.getTagNameElement(_end, 'span').style.cssText;
$$("a", { href: href, innerHTML: _rangselect[i].data, style: { cssText: _csstext }, target: "_blank" }, _frag);
} else {
$$("a", { href: href, innerHTML: _rangselect[i].innerHTML, style: { cssText: _rangselect[i].style.cssText }, target: "_blank" }, _frag);
}
}
}
}
_frag = U.UF.E.unifiedFormat(_frag); //进行格式整理
_frag.firstChild.firstChild.setAttribute("target", "_blank");
if (_startspan.innerHTML == "") {
U.selectEl(_startspan).remove();
}
if (_endspan.innerHTML == "") {
U.selectEl(_startspan).remove();
}
U.UF.E.insertContent(_frag, range, U.selectEl('#U_MD_O_H_wordEditor')[0]); //调用指定位置插入内容的函数
}
}
else {
//提示链接存在有误
U.alert('输入的链接有误,无法添加');
return false;
}
};
/* 超链接点击
*
*/
U.UF.E.addHref.click = function (e) {
if (document.getElementById('U_UF_E_herfAlert')) {//如果有弹框则删除
document.getElementById('U_UF_E_herfAlert').remove();
}
U.UF.EV.stopBubble(e);
var parent = U.selectEl("#U_MD_O_R_Parent")[0]; //获取编辑区
var _hyperlinkalert = $$('div', {
id: "U_UF_E_herfAlert",
style: {
"min-width": "250px", "max-width": "360px", height: "34px", background: "rgba(255,255,255,1)", border: "1px solid rgba(243,243,243,1)", "box-shadow": "0px 5px 5px 0px rgba(45,45,45,0.1)",
"border-radius": "2px", "line-height": "34px", "font-size": "12px", "font-family": "MicrosoftYaHei", "font-weight": "400", color: "rgba(48,126,209,1)", width: "fit-content",
width: "-webkit-fit-content", width: "-moz-fit-content", position: "absolute", zIndex: "999"
}
}, parent); //创建超链接弹框
var _link = $$('a', {
innerHTML: e.target.href,
style: {
"overflow": "hidden", "text-overflow": "ellipsis", "white-space": "nowrap", cursor: "pointer",
"max-width": "212px", "float": "left", "margin-left": "10px", "font-size": "14px"
}
}, _hyperlinkalert); //超链接按钮
var _rightButton = $$('div', { classname: "out_2", style: { "float": "right"} }, _hyperlinkalert);
var _unlink = $$('div', { innerHTML: "取消链接", style: { "float": "left", "margin-left": "20px", "margin-right": "10px", cursor: "pointer"} }, _rightButton); //取消链接按钮
var _modify = $$('div', { innerHTML: "修改", style: { "float": "left", "margin-left": "10px", "margin-right": "10px", cursor: "pointer"} }, _rightButton); //修改按钮
_link.onclick = function () {//链接的点击事件
U.UF.EV.stopBubble(e);
parent.blur();
window.open(e.target.href); //打开目标路径
}
_unlink.onclick = function () {//取消链接的点击事件
U.UF.EV.stopBubble(e);
e.target.parentElement.replaceChild($$('span', { innerText: e.target.innerText }), e.target);
_hyperlinkalert.remove(); //删除超链接弹框
parent.blur();
}
_modify.onclick = function () {//修改的点击事件
U.UF.EV.stopBubble(e);
U.UF.E.addHref(e.target); //修改弹框
parent.blur();
_hyperlinkalert.remove(); //删除超链接弹框
}
/*_hyperlinkalert.style.left = e.target.offsetLeft + "px";
_hyperlinkalert.style.top = e.target.offsetTop + 20 + "px"; //弹框的定位*/
//弹框的定位
console.log("超链接的位置", e.target.offsetLeft, e.target.offsetTop);
console.log("光标的位置", e.clientX, e.clientY);
console.log("滚动过的高度", U.selectEl('#U_MD_O_W_E_body')[0].offsetTop);
var EditorScrollTop = U.selectEl('#U_MD_O_R_Parent')[0].parentNode.scrollTop; //滚动高度
var EditorOffsetTop = U.selectEl('#U_MD_O_W_E_body')[0].offsetTop; //编辑器距窗口顶端的距离
_hyperlinkalert.style.left = e.clientX + "px";
_hyperlinkalert.style.top = e.clientY + EditorScrollTop - EditorOffsetTop + 12 + "px";
}
/* 在键盘输入的过程中处理
*
* @param editor {element} 编辑器的对象
*/
U.UF.E.key = function (editor) {
editor.editor.idarr = U.UF.E.key.getLineIdArr(editor); //初始化默认的行
//将定义的//将定义的方法做为对象的onkeydown方法
editor.onkeydown = function (e) {
if (!editor.editor.recordOpera.range) {
U.UF.E.recordRangeIndex(editor); //记录range处理
}
U.UF.E.key.keyDown(e, editor);
};
//失焦处理
editor.onblur = function (e) {
U.UF.E.key.blur(e, editor);
};
//将定义的方法做为对象的onkeyup方法
editor.onkeyup = function (e) {
U.UF.E.key.keyUp(e, editor);
};
//点击事件的处理
editor.onmouseup = function (e) {
U.UF.E.key.keyUp(e, editor, true);
};
editor.onclick = function (e) {
setTimeout(function () {
U.UF.E.key.click(e, editor);
}, 0);
};
//点击记录
editor.onmousedown = function (e) {
setTimeout(function () {
U.UF.E.recordRangeIndex(editor); //记录range处理
}, 0);
};
//粘贴处理
editor.onpaste = function (e) {
var _text = U.UF.E.onpaste(e, editor); //获取text的处理
//如果text有值则不粘贴图片
if (!_text) {
U.UF.E.pasteImage(e, editor);
}
};
editor.ondragenter = U.UF.E.pasteImage.ignoreDrag;
editor.ondragover = U.UF.E.pasteImage.ignoreDrag;
editor.ondrop = U.UF.E.pasteImage.drop;
// U.selectEl(editor).bind({ });
};
/* 定义click方法
*
* @param e {event} event对象
* @param editor {element} 编辑器对象
* */
U.UF.E.key.click = function (e, edit) {
var _nowel, _range = U.UF.E.getRangeAt(), //获取处理的光标
_startel = U.UF.E.getLineElement(_range.startContainer) //开始元素
if (_startel != (_nowel = U.UF.E.getLineElement(edit.editor.recordRange.startContainer))) {
edit.editor.recordHTML = _startel.outerHTML;
}
edit.editor.recordRange = _range;
U.selectEl('#U_UF_E_herfAlert').remove();
if (e.target.tagName == "A") { //如果点击标签为A标签
if (e.ctrlKey == true) { //Ctrl键是否按下
window.open(e.target.href); //打开超链接
} else {
U.UF.E.addHref.click(e);
}
}
else if (e.target.tagName == "IMG" && e.target.offsetParent.className != "U_MD_F_D") { //如果点击的元素为图片元素,且不是好友聊天状态中
edit.imgStretch.img = e.target; //记录当前图片到拉伸对象中
U.UF.E.picture.stretch.setPosition(edit.imgStretch, e); //定位显示拉伸区域
} else {//其余情况
edit.imgStretch.stretch.style.display = "none"; //影藏拉伸框
}
}
/* 定义blur方法
*
* @param e {event} event对象
* @param editor {element} 编辑器对象
* */
U.UF.E.key.blur = function (e, edit) {
var _range = U.UF.E.getRangeAt(); //获取处理的光标
if (_range) {
var _startel = U.UF.E.getLineElement(_range.startContainer); //开始元素
_oldstartel = U.UF.E.getLineElement(edit.editor.recordRange.startContainer); //获取上一步操作所在的行
if (_startel) {
edit.editor.recordRange = _range; //记录光标对象
edit.editor.recordHTML = _startel.outerHTML; //记录内容 以此判断内容是否发送变化
edit.editor.log && console.log({ updateLine: [_startel.id] }, "在哪行失焦的");
if (_oldstartel && _oldstartel.id != "U_MD_O_H_wordEditor" && _startel == _oldstartel && _oldstartel.outerHTML != edit.editor.recordHTML) {
U.UF.E.operationNotice({ updateLine: [_startel.id] }, edit);
clearTimeout(edit.editor.interval); //取消计时更新
}
}
}
}
/* 定义onkey方法
*
* @param e {event} event对象
* */
U.UF.E.key.keyDown = function (e, edit) {
var _range = U.UF.E.getRangeAt(); //获取处理的光标
if (!_range) { return; }
var _el,
_oldstartel,
_line,
_result,
_startel = U.UF.E.getLineElement(_range.startContainer), //开始元素
_endel = U.UF.E.getLineElement(_range.endContainer); //结束元素
var _code = e.keyCode || e.which || e.charCode; //键盘码
if (_startel && _endel) {
if (e.ctrlKey || e.metaKey) {
edit.editor.recordRange = _range; //记录光标对象
switch (_code) {
case 90: //撤销(后退)
U.UF.E.key.undo(e, edit);
return;
case 89: //重做(前进)
U.UF.E.key.redo(e, edit);
return;
}
}
//判断光标是否存在的处理
clearTimeout(edit.editor.interval); //继续编辑的话直接取消计时器
//可能一直按着删除键,那么第一行给删除就添加第一行
if (edit.childNodes.length == 0) {
_result = U.UF.E.key.addDelLine(edit, _range); //删除最后一行后添加删除元素
//判断选区中是否有内容,那么就会处理删除操作
edit.editor.idarr = U.UF.E.key.getLineIdArr(edit); //获取当前文档的id集合
//记录关闭记录
edit.editor.log && console.log(_result, "内容被情况默认添加行");
//记录最新的行
edit.editor.recordRange = _range; //记录光标对象
edit.editor.recordHTML = U.UF.E.getLineElement(_range.startContainer).outerHTML; //记录内容 以此判断内容是否发送变化
//添加新行的处理
U.UF.E.operationNotice(_result, edit);
return;
}
//如果是删除行的处理
if (_code == 9) {
_range.deleteContents(); //移除文字
var _frag = $$("frag");
var _fragel = $$('div', { innerHTML: " " });
_frag.appendChild(_fragel.childNodes[0]);
U.selectEl(_fragel).remove();
_range.insertNode(_frag); //插入需要写入的内容
U.UF.E.setRange(_range.endContainer, _range.endContainer, _range.endOffset, _range.endOffset, _range); //设置选区 重新聚焦
U.UF.EV.stopDefault(); //阻止浏览器默认行为
return;
}
//回车处理
if (_code === 13) {
if (!U.UF.E.getTagNameElement(_range.commonAncestorContainer, 'table')) {
_result = U.UF.E.key.addLine(_range); //调用方法,新建行
//判断选区中是否有内容,那么就会处理删除操作
edit.editor.idarr = U.UF.E.key.getLineIdArr(edit); //获取当前文档的id集合
U.UF.EV.stopDefault(); //阻止浏览器默认行为
//记录关闭记录
edit.editor.log && console.log(_result, "更新换行的行,添加新的行");
//记录最新的行
edit.editor.recordRange = _range; //记录光标对象
edit.editor.recordHTML = U.UF.E.getLineElement(_range.startContainer).outerHTML; //记录内容 以此判断内容是否发送变化
//添加新行的处理
U.UF.E.operationNotice(_result, edit);
}
}
else {
edit.editor.recordDownHTML = _startel.outerHTML; //记录内容 以此判断内容是否发送变化
if (_startel == _endel && edit.editor.recordRange.endOffset != edit.editor.recordRange.startOffset) {
setTimeout(U.UF.C.closure(function (startel, edit) {
if (edit.editor.recordHTML != startel.outerHTML) {
var _result = { updateLine: [_startel.id] };
U.UF.E.operationNotice(_result, edit);
edit.editor.log && console.log(_result, "存在选区的输入,即时更新");
edit.editor.recordHTML = startel.outerHTML;
edit.editor.recordRange = U.UF.E.getRangeAt();
}
}, [_startel, edit]), 0);
clearTimeout(edit.editor.interval); //取消计时更新
}
_line = U.UF.E.key.getLineIdArr(edit); //获取
_result = U.UF.E.diff(_line, edit.editor.idarr); //对比得到删除的值
edit.editor.idarr = _line; //删除信息
//换行后回调的处理
if (_result.deleteLine.length) {
U.UF.E.operationNotice(_result, edit);
edit.editor.log && console.log(_result, "未松开删除按钮时,删除了行");
if (_result.updateLine[0]) {
edit.editor.recordHTML = U.selectEl("#" + _result.updateLine[0])[0].outerHTML;
edit.editor.recordRange = _range;
}
}
//没有任何特殊处理等待一点五秒的处理
else {
//普通的编辑那边等待记录,1.5秒后告诉用户修改信息
edit.editor.interval = setTimeout(function () {
if (edit.editor.recordHTML != _startel.outerHTML) {
//回调处理
U.UF.E.operationNotice({ updateLine: [_startel.id] }, edit);
edit.editor.log && console.log({ updateLine: [_startel.id] }, "超时更新行");
//记录当前的行
edit.editor.recordRange = _range; //记录光标对象
edit.editor.recordHTML = _startel.outerHTML; //记录内容 以此判断内容是否发送变化
}
}, 1000);
}
}
}
};
/* 定义键盘离开事件
*
* @param e {event} event对象
* */
U.UF.E.key.keyUp = function (e, edit, click) {
var _range = U.UF.E.getRangeAt(); //获取处理的光标
var _code = e.keyCode || e.which || e.charCode; //键盘码
if (e.ctrlKey == false) {
U.selectEl(edit).removeClass('U_MD_O_ctrlPress');
}
if (_range) {
var _line,
_result,
_oldstartel,
_startel = U.UF.E.getLineElement(_range.startContainer), //开始元素
_endel = U.UF.E.getLineElement(_range.startContainer); //结束元素
//判断第一层是否被删除掉,如果不是
if (edit.childNodes.length == 0) {
_result = U.UF.E.key.addDelLine(edit, _range); //删除最后一行后添加删除元素
//判断选区中是否有内容,那么就会处理删除操作
edit.editor.idarr = U.UF.E.key.getLineIdArr(edit); //获取当前文档的id集合
//记录关闭记录
edit.editor.log && console.log(_result, "内容被情况默认添加行");
//记录最新的行
edit.editor.recordRange = _range; //记录光标对象
edit.editor.recordHTML = U.UF.E.getLineElement(_range.startContainer).outerHTML; //记录内容 以此判断内容是否发送变化
//添加新行的处理
U.UF.E.operationNotice(_result, edit);
return;
}
_oldstartel = U.UF.E.getLineElement(edit.editor.recordRange.startContainer); //记录之前开始的行
//开始位置切换了,那么就要把开始位置作为修改行
if (_oldstartel && (_oldstartel != edit && _oldstartel != _startel || (_startel == _oldstartel && _startel.outerHTML != edit.editor.recordDownHTML))) {
if (edit.editor.recordHTML != _oldstartel.outerHTML) {
var _result = { "updateLine": [_oldstartel.id] };
U.UF.E.operationNotice(_result, edit);
edit.editor.log && console.log(_result, "光标切换且内容发送变化时");
clearTimeout(edit.editor.interval); //取消计时更新
}
edit.editor.recordRange = _range;
edit.editor.recordHTML = _startel.outerHTML;
}
if (_code > 36 && _code < 41) {
U.UF.E.recordRangeIndex(edit); //记录range处理
}
_line = U.UF.E.key.getLineIdArr(edit); //获取
_result = U.UF.E.diff(_line, edit.editor.idarr);
edit.editor.idarr = _line;
//删除行的处理
if (_result.deleteLine.length) {
U.UF.E.operationNotice(_result, edit);
edit.editor.log && console.log(_result, "删除了行");
var _range = U.UF.E.getRangeAt();
edit.editor.recordRange = _range;
edit.editor.recordHTML = U.UF.E.getLineElement(_range.commonAncestorContainer).outerHTML;
clearTimeout(edit.editor.interval); //取消计时更新
}
U.UF.E.formatBrush(edit, false); //格式刷工具未启用状态 记录当前光标所在位置的文字样式
}
};
/* 把编辑器里面的内容转换为数组,数组的id为div的id。
*
* @param edit {element} 编辑器元素
* @return 数组
* */
U.UF.E.key.getLineIdArr = function (edit) {
var _i,
_arr = [];
//循环添加子元素
for (_i = 0; _i < edit.childNodes.length; _i++) {
//判断是否是行元素,只有行元素才记录
if (edit.childNodes[_i].tagName && edit.childNodes[_i].tagName.toLowerCase() === "div") {
//记录id和innerHTML
_arr.push({ "id": edit.childNodes[_i].id, "innerHTML": edit.childNodes[_i].outerHTML });
}
}
return _arr;
};
/* 比较编辑器列删除方法
*
* @param arr 进行比较的数组一
* @param arr 进行比较的数组二
*/
U.UF.E.diff = function (arr1, arr2) {
var temp = []; //临时数组1
var temparray = []; //临时数组2
var _i, _j; //循环变量
var _updateLine = [];
for (_i = 0; _i < arr1.length; _i++) {
temp[arr1[_i].id] = true; //把数组B的值当成临时数组1的键并赋值为真
}
for (_j = 0; _j < arr2.length; _j++) {
//同时把数组A的值当成临时数组1的键并判断是否为真,如果不为真说明没重复,就合并到一个新数组里,这样就可以得到一个全新并无重复的数组
if (!temp[arr2[_j].id]) {
if (_updateLine.length == 0) {
_updateLine.push(arr2[_j - 1].id);
}
temparray.push(arr2[_j].id);
}
}
return {
updateLine: _updateLine,
deleteLine: temparray
}; //返回差异值
}
/* 添加删除后的空行
*
* @param 编辑器元素
* @param range 可选
* @returns {*} 返回id
*/
U.UF.E.key.addDelLine = function (edit, range) {
var _range = range || U.UF.E.getRangeAt(), //获得光标的位置
_el = $$("div", { id: edit.editor.idarr[0] ? edit.editor.idarr[0].id : "e" + Guid.newGuid(), innerHTML: "
" }, edit); //重新创建第一行,值为原第一行的id
_range.selectNodeContents(_el); //将光标重选中添加的内容
_range.collapse(true); //向右折叠光标选区,设置结束点和开始点相同地方
return { addLine: [_el.id] };
}
/* 添加行
*
* @param range 可选
* @returns {*} 返回id
*/
U.UF.E.key.addLine = function (range) {
var _txtnode, //换行后的文本内容
_range = range || U.UF.E.getRangeAt(), //获得光标的位置
_startline = U.UF.E.getLineElement(_range.startContainer), //得到起始行的div
_el = $$('div', { id: "e" + Guid.newGuid(), style: { cssText: _startline.style.cssText} }), //需要添加的新元素
_result = {} //添加行后会影响变化的值
;
//删除已经选中的内容
if (_range.startOffset != _range.endOffset && _range.startContainer.innerHTML !== "
") {
_range.deleteContents();
}
_range.setEnd(_startline, _startline.childNodes.length); //设置光标结束点的位置
_txt = _range.extractContents(); //剪切文本处理
if ($("img", _txt)[0]) {
_txtnode = _txt;
}
//判断选取是否有内容,若有返回内容,反之添加一个br标签占位
else if (_txt.textContent.trim() === '') { //如果没有内容那么就添加一个br标签
_txtnode = $$('span', { style: { cssText: (_startline.lastChild && _startline.lastChild.style) ? _startline.lastChild.style.cssText : "" }, innerHTML: "
" });
}
//设置内容
else {
_txtnode = _txt;
}
//如果回车行的内容为"",且没有存在有效元素 那么就记录原有样式创建默认行
if (_startline.innerText == '' && !U.UF.E.validElement(_startline)) {
var _clone = _txtnode.nodeName == "SPAN" ? _txtnode : U.selectEl('span', _txtnode)[0]; //获取可克隆样式元素
var _content = _clone ? U.selectEl(_clone).clone()[0] : $$('span', { innerHTML: "
" }); //创建内容
_content.innerHTML = "
"; //设置默认内容
U.selectEl(_content).appendTo(_startline); //追加
}
_el.appendChild(_txtnode); //添加到创建的div里面
U.UF.E.insertAfter(_el, _startline); //添加到选中的div下面
_range.selectNodeContents(_el); //将光标重选中添加的内容
_range.collapse(true); //向右折叠光标选区,设置结束点和开始点相同地方
_result.addLine = [_el.id]; //添加新的行
_result.updateLine = [_startline.id]; //结束新的行
return _result; //返回添加的id
};
/* 判断某个元素内是否存在有效元素(存在内容、存在图片等),过滤无用元素(空span)
*
* @param el {element} 父级元素
* @returns {boole} 返回是否存在有效元素
*/
U.UF.E.validElement = function (el) {
var i, //定义循环变量
_children = el.children, //获取子级
_valid = false; //默认为没有有效元素
for (i = 0; i < _children.length; i++) { //循环处理
if (_children[i].nodeName == "BR") {
continue; //BR标签默认不做处理
}
else if (_children[i].nodeName == "IMG" || _children[i].innerText.length > 0 || ($('img', _children[i])[0] && _children[i].innerText.length == 0)) { //存在内容、存在图片则为有效元素
_valid = true;
}
else { //过滤无用标题
U.selectEl(_children[i]).remove();
i--;
}
}
return _valid; //返回结果
}
/* 在元素之后插入
*
* @param newEl {element} 插入的元素
* @param targetEl {element} 插入比对位置的元素
* */
U.UF.E.insertAfter = function (newEl, targetEl) {
//插入比对位置的元素的父级元素
var parentEl = targetEl.parentNode;
//如果当前元素的父级元素的最后一个元素为插入比对位置的元素
if (parentEl.lastChild === targetEl) {
//则使用appendChild直接添加到最后
parentEl.appendChild(newEl);
} else {
//否则则采用insertBefore 添加到插入比对位置的元素的上一个元素后
parentEl.insertBefore(newEl, targetEl.nextSibling);
}
//返回插入的元素
return newEl;
};
/* 复制格式
*
* 效果:把选区内的第一个或开始位置的字体样式复制,赋值到常量里
* */
U.UF.E.formatBrush = function (el, pattern) {
el = el || U.selectEl('#U_MD_O_H_wordEditor')[0];
if (U.UF.E.formatBrush.callBack && U.UF.E.formatBrush.pattern) {
U.UF.E.formatBrush.pattern = undefined;
U.selectEl(el).bind('mouseup', U.UF.E.formatBrush.callBack);
return;
}
var _style = pattern == false ? el.editor.recordRangeStyle : el.editor.brushStyle;
var range = U.UF.E.getRangeAt();
//获取选区
var _start = range.startContainer;
//选区开始位置
if (_start.nodeName == "DIV") {
//如果选区开始节点是div的话,代表添加过样式之类的
if (!range.cloneContents().children[0]) { //如果光标不能存在元素
_style = { // 情况格式刷数据
"font-family": "",
"font-size": "",
"font-weight": "",
"font-style": "",
"text-decoration": "",
"color": "",
"background-color": ""
};
pattern == false && (_style["text-align"] = "", _style["name"] = "");
return;
}
//获取选区内的第一个块状节点,的第一个文档节点
//_start = range.cloneContents().children[0].firstChild;
}
//循环常量brushstyle 刷子样式
var _value;
_start = _start.nodeType == 1 ? _start : _start.parentElement;
for (var name in _style) {
//把相应的样式名字,内容,赋值给相应的常量值
if (name == "font-size") {
_value = (parseFloat(_start.currentStyle[name]) * 72 / el.editor.dpi).toFixed(1) + "pt";
} else {
_value = _start.currentStyle[name];
}
_style[name] = _value;
}
if (pattern !== false) { //判断是否为默认记录样式处理
U.UF.E.formatBrush.pattern = pattern;
if (pattern !== true) {
U.selectEl(el).unbind("mouseup", U.UF.E.formatBrush.callBack); //是否单次取消
U.UF.E.formatBrush.callBack = function () { //设置鼠标起开处理
U.UF.E.fomatBrushNext(el); //设置样式
U.UF.E.formatBrush.pattern == undefined && U.selectEl(el).unbind("mouseup", U.UF.E.formatBrush.callBack); //是否单次取消
};
U.selectEl(el).bind('mouseup', U.UF.E.formatBrush.callBack);
}
}
else {
_style["text-align"] = U.UF.E.getLineElement(_start).currentStyle.textAlign;
_style["name"] = U.UF.E.getLineElement(_start).getAttribute('name');
U.UF.C.isFunction(el.editor.styleState) && el.editor.styleState(el.editor.recordRangeStyle);
}
};
/* 粘贴复制的样式
*
* 效果: 把常量复制到样式,粘贴到编辑器中
* */
U.UF.E.fomatBrushNext = function (el) {
U.UF.E.setRangeStyle({ "cssText": '' });
//在赋值相应的样式
U.UF.E.setRangeStyle(el.editor.brushStyle);
};
/* 附件功能
*
* @param input {element} input文件域元素
* @param editor {element} 编辑器元素
*/
U.UF.E.attachment = function (input, editor) {
if (input.files.length) { //判断是否存在文件
var _range = U.UF.E.getRangeAt(); //获取光标处理
U.UF.UP.inputUpload([input], 'http://upload.1473.cn/upload', function (r) { //调用统一上传处理
var _file, _filetype, _input = r.context[0];
var _imgtype = /.*(jpg|png|gif|jpeg|JPG|PNG|GIF|JPEG|bmp|BMP)$/;
var _filearray = []; //记录上传图片的数组
if (Object.prototype.toString.call(r.value[0]) != "[object Array]") { //根据返回值类型判断是否多图上传
_filearray = [r.value]; //单图用数组则直接记录
} else {
_filearray = r.value; //多图则直接替换即可
}
var _el, _frag = $$('frag');
for (i = 0; i < _filearray.length; i++) { //循环评接拼接
_file = _input.files[i];
_filetype = _file.name.substring(_file.name.lastIndexOf('.') + 1, _file.name.length); //获取文件后缀名
if (_filetype.match(_imgtype)) {//图片类型处理
_el = $$("div", {}, _frag); ;
$$('span', { innerHTML: '
' }, _el);
}
else { //其余文件类型处理
_el = U.UF.E.attachment.create(_file, _filearray[i][0], _filetype);
U.selectEl(_el).appendTo(_frag);
}
}
_frag = U.UF.E.unifiedFormat(_frag); //进行格式整理
U.UF.E.insertContent(_frag, _range, editor || U.selectEl('#U_MD_O_H_wordEditor')[0]); //调用指定位置插入内容的函数
}, [input]);
}
}
/* 创建附件
*
* @param input {element} input文件域元素
* @param editor {element} 编辑器元素
*/
U.UF.E.attachment.create = function (file, fileinfo, type) {
//, style: { "text-align": "center"}
var _attachment = $$("div", { className: "U_MD_O_attachment", id: "e" + Guid.newGuid(), contenteditable: "false" }),
_wrapper;
var _imgtype = /.*(jpg|png|gif|jpeg|bmp)$/;
//图片类型处理
if (type.match(_imgtype)) {
$$('span', { innerHTML: '
' }, _attachment);
} else {
var _videotype = /.*(mp4|avi|wmv|ogg|webm|mpg|mpeg)$/;
var _musictype = /.*(mp3|wav|mid|midi)$/;
$$("span", { innerHTML: "" }, _attachment);
_wrapper = $$("span", { contenteditable: "false" }, _attachment);
//音乐类型处理
if (type.match(_videotype)) {
$$('video', { src: "http://fs.1473.cn/" + fileinfo, controls: "controls", style: { "width": "530px", "height": "300px"} }, _wrapper);
}
//视频类型处理
else if (type.match(_musictype)) {
$$('audio', { src: "http://fs.1473.cn/" + fileinfo, controls: "controls" }, _wrapper);
}
//其余文件类型处理
else {
_wrapper.className = "U_MD_O_attachment_wrapper";
$$('span', { "className": "U_MD_O_attachment_wrapper_img", contenteditable: "false" }, _wrapper);
var _info = $$("span", { className: "U_MD_O_attachment_fileinfo", contenteditable: "false" }, _wrapper);
$$("span", { innerHTML: U.UF.E.attachment.fileNameSplice(file.name), contenteditable: "false" }, _info);
$$("span", { innerHTML: U.UF.C.computeFileSize(file.size), contenteditable: "false" }, _info);
$$("a", {
"href": "/Pages/Download.htm?id=" + fileinfo[2], //下载路径地址
fileid: fileinfo[2], //文件id
name: file.name, //文件名称
type: file.name.substring(file.name.lastIndexOf('.') + 1, file.name.length), //文件后缀名
target: "_blank",
innerHTML: "打开",
contenteditable: "false"
}, _wrapper);
}
$$("span", { innerHTML: "" }, _attachment);
}
return _attachment;
}
/* 获取附件名
*
* @param input {string} 文件名字
* @param editor {number} 最大长度
*/
U.UF.E.attachment.fileNameSplice = function (name, maxlength) {
maxlength = maxlength || 30;
var i, _index = 0, _gblen = 0, _start = "", _end = "";
for (i = 0; i < name.length; i++) {
if (name.charCodeAt(i) > 127 || name.charCodeAt(i) == 94) {
_gblen += 2;
} else {
_gblen++;
}
_gblen < maxlength / 2 - 2 && (_start += name[i]);
}
if (_gblen > maxlength) {
i = name.length;
while (_index < maxlength / 2 - 2) {
if (name.charCodeAt(i) > 127 || name.charCodeAt(i) == 94) {
_index += 2;
} else {
_index++;
}
_end = name[name.length - _index] + _end;
i--;
}
name = _start + "..." + _end;
}
return name;
}
/* 图片插入控件 效果:插入图片
*
* @param input {element} input文件域元素
* @param editor {element} 编辑器元素
*/
U.UF.E.picture = function (input, editor) {
if (input.files.length) { //判断是否存在文件
//给最后一个input以标识,在完成上传后更改input的value值为空,解决第二次上传onchange不响应的问题。
//按道理,如果能够精准判断到谁是最后一个上传最保险,但难以判断,此做法已经生效,有问题以后再考虑。
//js上传好像是数组最后一个最先上传,所以设置第0位进行传值。
input.files[0].input = input;
for (var i = 0; i < input.files.length;i++) {
U.UF.UP.HTML5.upload("http://upload.1473.cn/upload", input.files[i], function (r) {
//document.getElementById("product_u_i_displayImg").src = "http://fs.1473.cn/" + r.fileServerName;
//如需要生成缩略图,则调用
//调用上传图片控件
var _img = ''; //设置img元素字符串
//for (i = 0; i < _imgarray.length; i++) { //循环评接拼接
// $$("span", { innerHTML: "" }, _attachment);
_img += '
'; //图片元素拼接
//}
//$('#U_MD_O_H_wordEditor')[0],为什么要用或者?并且多条语句连写调试好困难,需要分开。
//找到编辑器
var _editor = editor || U.selectEl('#U_MD_O_H_wordEditor')[0];
U.UF.E.textFormat(_img, _editor); //生成img元素
//获取input控件,清空其值,解决第二次上传onchange不触发的问题。
var _input = r.input;
if (_input) {
_input.value = "";
}
}, function (r) { }, function (r) { });
}
}
}
// U.UF.E.picture = function (input, editor) {
// if (input.files.length) { //判断是否存在文件
// var _range = U.UF.E.getRangeAt(); //获取光标处理
// U.UF.UP.inputUpload([input], 'http://upload.1473.cn/upload', function (r) { //调用统一上传处理
// var _input = r.context[0];
// var _imgarray = []; //记录上传图片的数组
// if (Object.prototype.toString.call(r.value[0]) != "[object Array]") { //根据返回值类型判断是否多图上传
// _imgarray = [r.value]; //单图用数组则直接记录
// } else {
// _imgarray = r.value; //多图则直接替换即可
// }
// //调用上传图片控件
// var _img = ''; //设置img元素字符串
// for (i = 0; i < _imgarray.length; i++) { //循环评接拼接
// // $$("span", { innerHTML: "" }, _attachment);
// _img += '
'; //图片元素拼接
// }
// //$('#U_MD_O_H_wordEditor')[0],为什么要用或者?并且多条语句连写调试好困难,需要分开。
// //找到编辑器
// var _editor = editor || U.selectEl('#U_MD_O_H_wordEditor')[0];
// U.UF.E.textFormat(_img, _editor); //生成img元素
// }, [input]);
// }
// }
/* word复制粘贴图片及拖拽图片函数
*
* @param e {event} 事件对象
* @param editor {element} 编辑器元素
*/
U.UF.E.pasteImage = function (e, editor) {
e.preventDefault(); //阻止默认事件
var files = e.clipboardData.files; //获取文件列表
if (files.length && e.clipboardData.types.indexOf('Files') > -1) {
var filebtn = $$('input', { type: "file" }) //新建文件域
filebtn.files = files; //获取文件列表
U.UF.E.picture(filebtn); //上传图片
filebtn.remove(); //删除文件域
}
else {
return true;
}
}
/* 阻止拖拽默认事件
*
* @param e {event} 事件对象
*/
U.UF.E.pasteImage.ignoreDrag = function (e) {
//因为我们在处理拖放,所以应该确保没有其他元素会取得这个事件
e.stopPropagation();
e.preventDefault();
}
/* 拖拽上传处理
*
* @param e {event} 事件对象
*/
U.UF.E.pasteImage.drop = function (e) {
//取消事件传播及默认行为
e.stopPropagation();
e.preventDefault();
//取得拖进来的文件
var data = e.dataTransfer;
var files = data.files;
//将其传给真正的处理文件的函数
var filebtn = $$('input', { type: "file" })
filebtn.files = files;
U.UF.E.picture(filebtn, this);
filebtn.remove();
}
/* 拉伸处理
*
* @param el {element} 编辑器元素
*/
U.UF.E.picture.stretch = function (el) {
var _breadth = 12;
if (!el.imgStretch) {
var _img = $$("div", {
style: { display: "none", border: "1px dashed #535353", position: "absolute", minWidth: "30px", minHeight: "30px" }
}, document.body);
var _csstext = "width:" + _breadth + "px; height:" + _breadth + "px;position:absolute;z-index:999;background:url('/EditorImage/yuan1.png') no-repeat";
var _deviant = -_breadth / 2;
//创建虚拟框
el.imgStretch = {
//拉伸区域
stretch: _img,
//左上的按钮
nw: $$("div", { name: "nw", style: { cssText: _csstext, top: _deviant + "px", left: _deviant + "px", cursor: "nw-resize"} }, _img),
//右上的按钮
ne: $$("div", { name: "ne", style: { cssText: _csstext, top: _deviant + "px", right: _deviant + "px", cursor: "ne-resize"} }, _img),
//左下的按钮
sw: $$("div", { name: "sw", style: { cssText: _csstext, bottom: _deviant + "px", left: _deviant + "px", cursor: "sw-resize"} }, _img),
//右下的按钮
se: $$("div", { name: "se", style: { cssText: _csstext, bottom: _deviant + "px", right: _deviant + "px", cursor: "se-resize"} }, _img),
//上的按钮
n: $$("div", { name: "n", style: { cssText: _csstext, top: _deviant + "px", left: "calc(50% - " + -_deviant + "px)", cursor: "n-resize"} }, _img),
//下的按钮
s: $$("div", { name: "s", style: { cssText: _csstext, bottom: _deviant + "px", left: "calc(50% - " + -_deviant + "px)", cursor: "s-resize"} }, _img),
//左的按钮
w: $$("div", { name: "w", style: { cssText: _csstext, left: _deviant + "px", top: "calc(50% - " + -_deviant + "px)", cursor: "w-resize"} }, _img),
//右的按钮
e: $$("div", { name: "e", style: { cssText: _csstext, right: _deviant + "px", top: "calc(50% - " + -_deviant + "px)", cursor: "e-resize"} }, _img),
//左边的拖动虚拟线
l: $$("div", { name: "l", style: { position: "absolute", cursor: "e-resize", left: "-1px", width: "3px", height: "100%"} }, _img),
//右边的拖动虚拟线
r: $$("div", { name: "r", style: { position: "absolute", cursor: "e-resize", right: "-1px", width: "3px", height: "100%"} }, _img),
//顶部的拖动虚拟线
t: $$("div", { name: "t", style: { position: "absolute", cursor: "n-resize", top: "-1px", width: "100%", height: "3px"} }, _img),
//底部的拖动虚拟线
b: $$("div", { name: "b", style: { position: "absolute", cursor: "n-resize", bottom: "-1px", width: "100%", height: "3px"} }, _img),
maxWidth: U.selectEl(el)[0].offsetWidth
};
}
//绑定拖拽事件
new U.UF.E.picture.stretch.bindEvent(el);
};
/* 拉伸事件绑定
*
* @param el {element} 编辑器元素
*/
U.UF.E.picture.stretch.bindEvent = function (el) {
this.el = el; //设置编辑器元素
this.init(); //初始化设置
}
/* 拖拽方法
*
*/
U.UF.E.picture.stretch.bindEvent.prototype = {
//初始化
init: function () {
for (key in this.el.imgStretch) { //绑定所有可拉伸区域事件
key !== "stretch" && key !== "maxWidth" && this.el.imgStretch[key].addEventListener('mousedown', this.mouseDown.bind(this)); //绑定事件
}
document.body.addEventListener('mousemove', this.mouseMove.bind(this)); //绑定事件
document.body.addEventListener('mouseup', this.mouseUp.bind(this)); //绑定事件
},
//鼠标按下事件
mouseDown: function (e) {
this.name = e.target.name; //记录元素标识
this.stratX = e.clientX; //起始位置X
this.stratY = e.clientY; //起始位置Y
this.down = true; //按下标识
},
//鼠标移动事件
mouseMove: function (e) {
if (this.down) { //如果鼠标按下
//计算移动的坐标距离
var _moveX = e.clientX - this.stratX;
var _moveY = this.stratY - e.clientY;
var _click = this.name; //获取点击名称
//判断是否可以拉伸
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
//清空移动的数据
if (_click.length == 2 || _click == "w" || _click == "e" || _click == "l" || _click == "r") {
//如果是右方的拖动就移动距离相反
(_click == "w" || _click == "sw" || _click == "nw" || _click == "l") && (_moveX = -_moveX);
//处理虚拟框的宽高,和圆圈位置
U.UF.E.picture.stretch.moveX(this.el, this.el.imgStretch, _moveX);
}
if (_click.length == 2 || _click == "n" || _click == "s" || _click == "t" || _click == "b") {
//如果是上方的拖动就移动距离相反
(_click == "n" || _click == "nw" || _click == "ne" || _click == "t") && (_moveY = -_moveY)
//处理虚拟框的宽高,和圆圈位置
U.UF.E.picture.stretch.moveY(this.el.imgStretch, _moveY);
}
//设置新的对比起始位置
this.stratX = e.clientX;
this.stratY = e.clientY;
}
},
//鼠标松开事件
mouseUp: function (e) {
if (this.down) { //如果鼠标已按下
var _imgstretch = this.el.imgStretch; //获取拉伸元素集合
_imgstretch.img.style.width = _imgstretch.stretch.offsetWidth + "px"; //赋值
_imgstretch.img.style.height = _imgstretch.stretch.offsetHeight + "px"; //赋值
U.UF.E.picture.stretch.setPosition(_imgstretch, e); //执行点击事件重新定位
this.down = false; //设置按下标识结束
}
}
}
/* 设置拉伸框位置
*
* @param obj {object} 拉伸对象
* @param event [event} 事件对象
*/
U.UF.E.picture.stretch.setPosition = function (obj, event) {
var _stretch = obj.stretch; //拉伸盒子元素
var _imgel = obj.img; //被拉伸图片
//显示虚拟框,设置虚拟框的位置,大小
_stretch.style.display = "block"; //显示拉伸元素
var _imgelattr = _imgel.getBoundingClientRect(); //获取位置大小属性
if (event.clientX == event.pageX && event.clientY == event.pageY) { //当页面没有滚动时
_stretch.style.left = _imgelattr.left + "px"; //设置值
_stretch.style.top = _imgelattr.top + U.selectEl('body')[0].scrollTop + "px"; //设置值
} else {
var _offset = U.UF.E.picture.parentOfferset(_imgel, { "offsetLeft": 0, "offsetTop": 0 }); //获取父亲层的边距
_stretch.style.left = _imgel.offsetLeft + _offset.offsetLeft + parseInt($(_imgel).css("padding-left")) + "px"; //设置值
_stretch.style.top = _imgel.offsetTop + _offset.offsetTop + parseInt($(_imgel).css("padding-top")) + "px"; //设置值
}
_stretch.style.width = _imgelattr.width - 2 + "px"; //设置宽度
_stretch.style.height = _imgelattr.height - 2 + "px"; //设置高度
var _objattr = _stretch.getBoundingClientRect(); //获取位置大小属性
var _breadth = obj.n.offsetWidth / 2; //计算远点大小偏移值
obj.n.style.left = _objattr.width / 2 - _breadth + "px"; //设置顶部中心原点居中
obj.w.style.top = _objattr.height / 2 - _breadth + "px"; //设置底部中心原点居中
obj.s.style.left = _objattr.width / 2 - _breadth + "px"; //设置左部中心原点居中
obj.e.style.top = _objattr.height / 2 - _breadth + "px"; //设置右部中心原点居中
}
/* 左右拖拽方法
*
* @param el [element} 编辑器对象
* @param obj {object} 拉伸对象
* @param moveX [int} 移动距离
*/
U.UF.E.picture.stretch.moveX = function (el, obj, moveX) {
var _stretch = obj.stretch; //拉伸盒子元素
if ((parseInt(_stretch.style.width) + moveX < obj.maxWidth && parseInt(_stretch.style.width) + moveX > 30)) { //判断拉伸后是否超出限制
var _align = el.editor ? el.editor.recordRangeStyle["text-align"] : ""; //获取对齐方式
switch (_align) { //判断对齐方式
case "end": //end 为 right
case "right": //居右处理
_stretch.style.left = _stretch.offsetLeft - moveX + 'px'; //设置left值
U.selectEl(_stretch)[0].style.width = parseInt(_stretch.style.width) + moveX + "px"; //设置宽度
break;
case "center": //居中处理
_stretch.style.width = parseInt(_stretch.style.width) + moveX + 'px'; //设置宽度
_stretch.style.left = parseFloat(_stretch.style.left) - moveX / 2 + 'px'; //设置偏左值
break;
default: //居左处理
_stretch.style.width = parseInt(_stretch.style.width) + moveX + "px"; //设置宽度
}
obj.n.style.left = obj.s.style.left = _stretch.offsetWidth / 2 - obj.s.offsetWidth / 2 + "px"; //设置顶部 底部原点居中
}
};
/* 上下拖拽方法
*
* @param obj {object} 拉伸对象
* @param moveX [int} 移动距离
*/
U.UF.E.picture.stretch.moveY = function (obj, moveY) {
var _stretch = obj.stretch; //拉伸盒子元素
//变化虚拟框的宽度
_stretch.style.height = _stretch.offsetHeight - 2 - moveY + "px";
//变化左、右按钮的位置
obj.w.style.top = obj.e.style.top = _stretch.offsetHeight / 2 - obj.w.offsetWidth / 2 + 'px';
};
/* 得到父亲层的边距
*
* @param obj {object} 拉伸对象
* @param moveX [int} 移动距离
* @return {object} 返回父亲层的边距
*/
U.UF.E.picture.parentOfferset = function (obj, json) {
var _offset = {};
//判断父亲层的左边距是否为空
if (obj.offsetParent.offsetLeft != 0) {
//如果有就赋值
_offset.offsetLeft = obj.offsetParent.offsetLeft;
} else {
//没有就赋值0
_offset.offsetLeft = 0;
}
//判断父亲层的上边距是否为空
if (obj.offsetParent.offsetTop != 0) {
//如果有就赋值
_offset.offsetTop = obj.offsetParent.offsetTop;
} else {
//没有就赋值0
_offset.offsetTop = 0;
}
json.offsetLeft = _offset.offsetLeft + json.offsetLeft;
json.offsetTop = _offset.offsetTop + json.offsetTop;
//如果 父亲层的左边距和上边距都为0 代表,没有边距了可以返回了
if (_offset.offsetTop == 0 && _offset.offsetLeft == 0) {
return json;
} else {
return U.UF.E.picture.parentOfferset(obj.offsetParent, json);
}
}
//#region 协同的处理
/*
* word 消息类
* 参数一 : id 行id
* 参数二 : type 操作类型
* 参数三 : content 行内容
* 参数四 : next 下一行
*/
U.UF.E.editInfo = function (id, content, next) {
var _data = {
id: id, //操作ID
content: content, //内容
nextId: next //下一行ID
};
return _data;
};
/*
* 协同的处理
* @param e {event} event对象
* @param e {element} 编辑器对象
*/
U.UF.E.operationNotice = function (operaRecord, editor) {
var _opera = {}; //记录操作记录
//是否有添加行的处理
if (operaRecord.addLine) {
_opera.addLine = U.UF.E.addLineMessage(operaRecord.addLine, editor); //得到操作行的协同记录
}
//是否有修改行的处理
if (operaRecord.updateLine) {
_opera.updateLine = U.UF.E.updateLineMessage(operaRecord.updateLine, editor); //得到修改行的协同记录
}
//是否有删除行的处理
if (operaRecord.deleteLine) {
_opera.deleteLine = U.UF.E.deleteLineMessage(operaRecord.deleteLine, editor); //得到删除行的协同记录
}
//记录前进后退
U.UF.E.setRecord(operaRecord, editor);
//协同回调
if (U.UF.C.isFunction(editor.editor.operaNotice)) {
editor.editor.operaNotice(_opera);
}
}
/*
* 添加行
* @param {array} 添加行的对象
* @param {element} 编辑器对象
*/
U.UF.E.addLineMessage = function (array, edit) {
var _i,
_nextlineid,
_el,
_editinfo,
_message = []
;
//循环添加行,获取数据
for (_i = 0; _i < array.length; _i++) {
_el = U.selectEl('#' + array[_i])[0]; //获取添加行的元素
_nextlineid = (_nextlineid = U.selectEl('#' + array[_i])[0].nextElementSibling) ? _nextlineid.id : null; //判断是否有下一行有返回id ,没有返回null
_editinfo = U.UF.E.editInfo(array[_i], _el.outerHTML, _nextlineid); //初始化word信息处理
_message.push(_editinfo); //添加数据
}
return _message;
};
/*
* 修改行内容
* @param {array} 添加行的对象
* @param {element} 编辑器对象
*/
U.UF.E.updateLineMessage = function (array, edit) {
var _i,
_el,
_editinfo,
_message = [];
for (_i = 0; _i < array.length; _i++) {
_el = U.selectEl('#' + array[_i])[0]; //获取修改行的信息
_editinfo = U.UF.E.editInfo(array[_i], _el.outerHTML, null); //初始化word信息处理
_message.push(_editinfo); //添加数据
}
return _message;
};
/*
* 删除行
* @param {array} 删除的行
* @param {element} 编辑器对象
*/
U.UF.E.deleteLineMessage = function (array, edit) {
var _i,
_editinfo,
_message = []
;
for (_i = 0; _i < array.length; _i++) {
_editinfo = U.UF.E.editInfo(array[_i], "", null); //初始化word信息处理
_message.push(_editinfo); //添加数据
}
return _message;
};
//#endregion
//#region 前进后退方案
/*
* 添加前进后退内容(当)
* @param {array} 添加行的对象
* @param {element} 编辑器对象
*/
U.UF.E.setRecord = function (opera, editor) {
if (editor.editor.isrecord && editor.editor.recordOpera && editor.editor.recordOpera.range) {
editor.editor.recordsEditor.splice(editor.editor.recordsEditorIndex, editor.editor.recordsEditor.length - editor.editor.recordsEditorIndex);
editor.editor.recordsEditorIndex = editor.editor.recordsEditor.length;
//插入记录
editor.editor.recordsEditor.push({
"opera": opera,
"recordLine": editor.editor.recordOpera
});
editor.editor.recordsEditorIndex++;
//重新记录
editor.editor.recordOpera = { "line": U.UF.E.key.getLineIdArr(editor) };
U.UF.E.recordRangeIndex(editor);
}
editor.editor.isrecord = true;
}
/*
* 记录光标位置和内容
* @param {array} 添加行的对象
* @param {element} 编辑器对象
*/
U.UF.E.recordRangeIndex = function (editor) {
//编辑器的光标处理
var _range = U.UF.E.getRangeAt(); //得到光标
if (_range) {
var _startel = U.UF.E.getLineElement(_range.startContainer), //开始行
_endel = U.UF.E.getLineElement(_range.endContainer) //结束行
;
if (_startel && _endel) {
//开始和结束行的处理
editor.editor.recordOpera.range = {
"startid": _startel.id,
"endid": _endel.id,
"endOffset": _range.endOffset, //
"startOffset": _range.startOffset,
"start": U.UF.E.getElementByAncestorsIndex(_startel, _range.startContainer),
"end": U.UF.E.getElementByAncestorsIndex(_endel, _range.endContainer)
};
}
}
}
/*
* 记录
* @param {Element} 祖先元素
* @param {Element} 子元素
*/
U.UF.E.getElementByAncestorsIndex = function (el, childel) {
var i, j, _child, _cindex;
//获取开始位置的处理
if (el !== childel) {
_child = el.childNodes;
for (i = 0; i < _child.length; i++) {
//聚焦到子元素下的处理
if (_child[i] == childel) {
_cindex = i;
break;
}
//聚焦到子子元素的处理
else if (U.UF.EL.isChild(_child[i], childel)) {
_child = _child[i].childNodes;
//循环子元素得到位置
for (j = 0; j < _child.length; j++) {
if (_child[j] == childel) {
_cindex = [i, j];
break;
}
}
}
}
}
return _cindex;
}
/* 定义撤销(后退)函数
*
* @param e {event} event对象
* @param editor {element} 编辑器对象
* */
U.UF.E.key.undo = function (e, editor) {
var i, j, k,
_info,
_operarecord = {},
_index = editor.editor.recordsEditorIndex - 1,
_record,
_line;
if (_index > -1 && editor.editor.recordsEditor.length >= _index) {
_record = editor.editor.recordsEditor[_index];
_line = _record.recordLine.line;
//如果存在记录
if (_record.recordLine) {
for (i in _record.opera) {
switch (i) {
//添加行的处理,如果是
case "addLine":
//如果是后退添加行,那么直接删除
for (j = 0; j < _record.opera[i].length; j++) {
U.UF.E.deleteEditorLine(_record.opera[i][j]);
}
break;
case "updateLine":
//如果是后退添加行,那么直接删除
for (j = 0; j < _record.opera[i].length; j++) {
U.UF.E.updateEditorLine({ "id": _record.opera[i][j], "content": U.UF.E.getLineContentById(_line, _record.opera[i][j]) });
}
break;
case "deleteLine":
//如果是后退添加行,那么直接删除
for (j = 0; j < _record.opera[i].length; j++) {
_info = U.UF.E.getLineInfoById(_line, _record.opera[i][j]); //获取行信息
U.UF.E.addEditorLine({ "nextId": _info.next ? _info.next.id : null, "content": _info.info.innerHTML }, editor); //删除后添加回信息
}
break;
}
}
U.UF.E.setRecordRange(_record.recordLine.range); //设置光标
//如果是最后的测回,那么添加一个可前进的记录
if (editor.editor.recordsEditor.length == _index + 1) {
U.UF.E.setRecord(_record.opera, editor); //重新记录
}
editor.editor.recordsEditorIndex--;
editor.editor.isrecord = false;
}
}
//取消浏览器默认事件
U.UF.EV.stopDefault();
}
/* 定义重做(前进)函数
*
* @param e {event} event对象
* @param editor {element} 编辑器对象
* */
U.UF.E.key.redo = function (e, editor) {
var i, j, k,
_info,
_operarecord = {},
_index = editor.editor.recordsEditorIndex,
_record,
_line;
if (_index > -1 && _index < editor.editor.recordsEditor.length) {
_record = editor.editor.recordsEditor[_index];
_line = _record.recordLine.line;
//如果存在记录
if (_record.recordLine) {
for (i in _record.opera) {
switch (i) {
//添加行的处理,如果是
case "addLine":
//如果是后退添加行,那么直接删除
for (j = 0; j < _record.opera[i].length; j++) {
_info = U.UF.E.getLineInfoById(_line, _record.opera[i][j]); //获取行信息
U.UF.E.addEditorLine({ "nextId": _info.next ? _info.next.id : null, "content": _info.info.innerHTML }, editor); //删除后添加回信息
}
break;
case "updateLine":
//如果是后退添加行,那么直接删除
for (j = 0; j < _record.opera[i].length; j++) {
U.UF.E.updateEditorLine({ "id": _record.opera[i][j], "content": U.UF.E.getLineContentById(_line, _record.opera[i][j]) });
}
break;
case "deleteLine":
//如果是后退添加行,那么直接删除
for (j = 0; j < _record.opera[i].length; j++) {
U.UF.E.deleteEditorLine(_record.opera[i][j]);
}
break;
}
}
U.UF.E.setRecordRange(_record.recordLine.range); //设置光标
editor.editor.isrecord = false;
editor.editor.recordsEditorIndex++;
}
}
//取消浏览器默认事件
U.UF.EV.stopDefault();
}
/* 光标聚焦
*
* @param e {object} 自定义光标对象
*/
U.UF.E.setRecordRange = function (range) {
var _startel,
_start,
_endel,
_end;
//光标开始位置和开始元素的处理
if (range.startid && U.selectEl("#" + range.startid)[0]) {
_start = range.startOffset; //开始位置
//开始元素的获取
if (range.start.length) { //如果是#text标签的处理
_startel = U.selectEl("#" + range.startid)[0].childNodes[range.start[0]].childNodes[range.start[1]];
}
else { //如果是span标签的处理
_startel = U.selectEl("#" + range.startid)[0].childNodes[range.start];
}
}
//光标结束位置的处理
if (range.endid && U.selectEl("#" + range.endid)[0]) {
_end = range.endOffset; //结束的位置
//结束元素的获取
if (range.start.length) { //如果是#text标签的处理
_endel = U.selectEl("#" + range.endid)[0].childNodes[range.end[0]].childNodes[range.end[1]];
}
else {//如果是span标签的处理
_endel = U.selectEl("#" + range.endid)[0].childNodes[range.end];
}
}
//选择光区聚焦
U.UF.E.setRange(_startel, _endel, _start, _end)
}
/* 设置记录内容
*
* @param e {event} event对象
* @param editor {element} 编辑器对象
*/
U.UF.E.getLineContentById = function (line, id) {
for (var i = 0; i < line.length; i++) {
if (line[i].id == id) {
return line[i].innerHTML;
}
}
return "";
}
/* 获取行信息
*
* @param e {array} 行数组
* @param editor {string} id
*/
U.UF.E.getLineInfoById = function (line, id) {
for (var i = 0; i < line.length; i++) {
if (line[i].id == id) {
return { "pre": line[i - 1], "next": line[i + 1], "info": line[i] }
}
}
return null;
}
/*
* 根据操作记录撤回或者前进修改信息
* @param {object} 操作的行
*/
U.UF.E.updateEditorLine = function (opera) {
//判断修改的元素是否存在
if ($('#' + opera.id)[0]) {
U.selectEl('#' + opera.id)[0].outerHTML = opera.content;
}
else {
console.log('updateError', opera.id);
}
};
/*
* 根据操作记录撤回或者前进删除信息
* @param {object} 操作的行
*/
U.UF.E.deleteEditorLine = function (opera) {
//删除行的处理
U.selectEl('#' + opera.id).remove();
};
/*
* 根据操作记录撤回或者前进添加信息
* @param {object} 操作的行
* @param {element} 编辑器元素
*/
U.UF.E.addEditorLine = function (opera, editor) {
editor = editor || U.selectEl('#U_MD_O_H_wordEditor')[0]; //
var _next,
_line = $$("div", {}, editor);
//判断有没有nextid,nextid是否存在
if (opera.nextId && (_next = U.selectEl('#' + opera.nextId))[0]) {
_next.Parent().insertBefore(_line, _next[0]); //有的话插入在nexid 元素前
}
U.selectEl(_line)[0].outerHTML = opera.content; //替换内容
}
//#endregion