Editor.js 118 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727
  1. /**
  2. *编辑使用区域,
  3. *格式定义:1、行元素为div
  4. * 2、里面样式元素为span元素设置style
  5. * 3、编辑功能点击按钮为button按钮 统一设置样式 padding: 0; background: 0 0; outline: 0; -moz-outline: 0; border: 0; display: block; cursor: pointer; margin: 0;
  6. */
  7. Namespace.register("U.UF.E");
  8. /* 初始化编辑器,让编辑器的格式符合
  9. *
  10. * @param el {element} 编辑的元素
  11. * @param callback {function} 非必传 操作处理函数
  12. * 操作处理函数 该函数默认第一个参数为操作记录。
  13. * 格式形如 : { updateLine : [ 修改行ID, 修改行ID,], addLine : [添加行ID], deleteLine : [删除行ID] }
  14. * @param content {string} 默认添加的内容
  15. * @param stylestate {function} 非必传 光标所在行样式状态处理
  16. */
  17. U.UF.E.initEditor = function (el, synergy, content, stylestate) {
  18. //el是编辑器加载到哪个元素下必须传的元素 第二个是编辑器触发的回调函数 第三个是编辑器需要加载的内容 第四个是编辑器内容变化的时候的回调函数
  19. //这个函数主要的逻辑内容是实现编辑器初始化内容,如果内容为空的时候那么初始化首行
  20. //编辑器需要初始化内容的时候
  21. if (content) {
  22. //先加载内容
  23. el.innerHTML = content; //设置内容
  24. el.focus(); //编辑器编辑区域聚焦
  25. //判断加载的内容是否是通过1473编辑器初始化过的内容,如果是没有初始化过的内容,那么重新初始化
  26. if (!$("div", el)[0] || U.selectEl("div", el)[0].id.length != "37") {
  27. el.innerHTML = ""; //清理内容
  28. U.UF.E.textFormat(content, el); //重新加载内容
  29. U.selectEl("div", el)[0].focus(); //聚焦
  30. }
  31. //暂时先注释掉,去除外部引入的内容有包含可编辑元素,还有设置了不可编辑状态,导致文档不能流畅使用
  32. // U.selectEl("textarea", el).remove(); //去除textarea
  33. // U.selectEl("div", el).addAttrArray({ "contentEditable": "" }); //设置可编辑
  34. }
  35. //没有内容的初始化
  36. else {
  37. //创建行元素
  38. var _div = $$("div", { "id": "e" + Guid.newGuid(), "innerHTML": content || "<span><br /></span>" }, el); //创建一个编辑的div进行编辑处理
  39. el.focus(); //编辑器编辑区域聚焦
  40. }
  41. //上面处理内容后,下面初始化
  42. U.UF.E.variable(el, synergy, stylestate); //初始化全局变量
  43. //事件监听
  44. U.UF.E.key(el); //键盘监听
  45. //设置样式
  46. U.UF.E.formatBrush(el, false); //格式刷工具未启用状态 记录当前光标所在位置的文字样式
  47. //创建图片拉伸控件
  48. U.UF.E.picture.stretch(el); //加载图片拉伸控件
  49. //得到现在编辑器使用的行
  50. el.idarr = U.UF.E.key.getLineIdArr(el);
  51. //设计前进后退行记录
  52. el.editor.recordOpera = { "line": el.idarr }
  53. return U.UF.E.getRangeAt(); //得到光标
  54. }
  55. /* 初始化编辑器全局变量
  56. *
  57. * @param el {element} 编辑的元素
  58. */
  59. U.UF.E.variable = function (el, synergy, stylestate) {
  60. var _range = U.UF.E.getRangeAt(); //得到光标
  61. //编辑器全局区域
  62. el.editor = {
  63. "isrecord": true,
  64. "idarr": [], //删除或者添加变化的数组
  65. //格式刷全局变量
  66. "brushStyle": {
  67. "font-family": {},
  68. "font-size": {},
  69. "font-weight": {},
  70. "font-style": {},
  71. "text-decoration": {},
  72. "color": {},
  73. "backgroundColor": {}
  74. },
  75. //外部引入的内容需要保留的对象
  76. "recordRangeStyle": {
  77. "font-family": "",
  78. "font-size": "",
  79. "font-weight": "",
  80. "font-style": "",
  81. "text-decoration": "",
  82. "color": "",
  83. "backgroundColor": ""
  84. },
  85. "styleState": stylestate, //样式状态管理回调
  86. "maxWidth": U.selectEl(el)[0].offsetWidth, //记录最大宽度
  87. "operaNotice": synergy, //设置编辑器处理的回调函数
  88. "recordRange": _range, //当前使用的光标
  89. "recordHTML": "", //当前操作行的内容
  90. "recordOpera": {}, //记录行内容
  91. "dpi": U.UF.CI.getDPI()[0], //获取屏幕分辨率
  92. "log": true, //是否输出日志
  93. "recordsEditor": [], //操作记录数组
  94. "recordsEditorIndex": 0 //当前操作记录位置
  95. };
  96. }
  97. /* 粘贴的处理
  98. *
  99. * @param e {event} 操作对象
  100. * @param editor {element} 编辑器
  101. * @param text {string} 需要处理的文字
  102. */
  103. U.UF.E.onpaste = function (e, editor, text) {
  104. var _content, event = e || window.event;
  105. if (text != undefined) {
  106. _text = text;
  107. }
  108. else {
  109. _text = U.UF.C.pasteText();
  110. }
  111. _content = _text.SplitAngleBrackets();
  112. if (_content && _content.length < 2) {
  113. //普通文本替换的处理
  114. _text = "<div>" + _text.replaceAngleBrackets().replace(/\r\n/g, "</div><div>").replace(/ /g, " &nbsp;") + "</div>";
  115. }
  116. //进行br标签的正则替换 br标签做为独立行标签
  117. _text = _text.replace(/<(BR)[^<>]*>/ig, "</div></br><div>").replace(/&#32;/g, "&nbsp;");
  118. _text.trim() != "" && U.UF.E.textFormat(_text, editor); //文字格式化处理
  119. U.UF.EV.stopDefault(); //去除默认事件
  120. return _text.trim();
  121. }
  122. /* 粘贴的处理
  123. *
  124. * @param text {string} 需要处理的文字
  125. * @param range {object} 光标对象
  126. *
  127. */
  128. U.UF.E.textFormat = function (text, editor) {
  129. var _editor = editor || this.editor;
  130. var _range = U.UF.E.getRangeAt(), //获取光标选取
  131. _div = $$("div", { "innerHTML": text, "style": { "display": "none"} }, U.selectEl("body")[0]), //内容
  132. _frag = U.UF.E.unifiedFormat(_div); //获取拆分的值
  133. U.UF.E.insertContent(_frag, _range, _editor); //调用指定位置插入内容的函数
  134. //获取table进行初始化
  135. var _table = U.selectEl('table', _editor);
  136. //表格处理 写在这里
  137. for (var i = _table.length - 1; i >= 0; i--) {
  138. U.UF.E.table.load(_table[i]);
  139. }
  140. U.selectEl(_div).remove(); //删除div元素
  141. }
  142. /* 在指定位置插入内容
  143. *
  144. * @param el {element} 插入的元素 frag临时标签
  145. * @param range {object} 光标对象
  146. *
  147. */
  148. U.UF.E.insertContent = function (el, range, editor) {
  149. range = range || U.UF.E.getRangeAt(); //获取光标选取
  150. //html5浏览器.此处添加了&& el.textContent会导致论坛上传不了图片,需要再次研究
  151. if (window.getSelection) {
  152. //if (window.getSelection && el.textContent) {
  153. var _i, //循环变量
  154. _frag,
  155. _stylecsstext,
  156. _span,
  157. _child = el.childNodes, //获取插入元素的所有孩子节点
  158. _lastchild, //记录最后一个孩子节点变量
  159. _extractcontent, //记录删除选区内容
  160. _record,
  161. _focusel,
  162. _frag = $$("frag"), //创建frag 临时标签
  163. _startline = range.startContainer == editor ? editor.children[0] : U.UF.E.getLineElement(range.startContainer), //选择的行
  164. _endline = range.endContainer == editor ? editor.children[0] : U.UF.E.getLineElement(range.endContainer), //选择的列
  165. _selection = window.getSelection()//获取选区函数
  166. ;
  167. if (editor.innerHTML == "") {
  168. _record = { addLine: [] };
  169. for (_i = 0; _i < _child.length; ) {
  170. _record.addLine.push(_child[_i].id);
  171. //循环把选区内容元素插入到临时标签中
  172. editor.appendChild(_child[_i]);
  173. }
  174. U.UF.E.elementFocus(range, editor.children[0], true); //重新聚焦元素
  175. editor.editor.recordHTML = editor.children[editor.children.length - 1].outerHTML;
  176. }
  177. else {
  178. _record = { updateLine: [_startline.id], addLine: [] };
  179. //移除选取的内容
  180. range.deleteContents(); //移除文字
  181. _selection.removeAllRanges(); //移除选取
  182. //剪切区域移除br标签,反正br导致多次换行
  183. // U.selectEl("br", _startline).remove(); //移除所有的br标签
  184. // U.selectEl("br", _endline).remove(); //移除所有的br标签
  185. _lastchild = _endline.lastChild; //获取结束行最后一个元素
  186. //粘贴的第一行有内容的处理
  187. if (_lastchild && (_lastchild.innerHTML != undefined || _lastchild.data != undefined)) {
  188. _stylecsstext = (_lastchild.style || _lastchild.parentNode.style).cssText; //首行的样式处理
  189. _focusel = _child[_child.length - 1].childNodes[_child[_child.length - 1].childNodes.length - 1] || _child[_child.length - 1]; //剪切后最后聚焦的元素
  190. //结束行是向前插入,先把结束好的文字剪切走
  191. try {
  192. range.setEnd(_lastchild, _lastchild.innerHTML != undefined ? 1 : _lastchild.data.length); //设置光标结束的位置
  193. }
  194. catch (e) {
  195. range.setEnd(_lastchild, 0); //设置光标结束的位置
  196. }
  197. _extractcontent = range.extractContents(); //记录删除选区内容
  198. //把最后一行选取的内容如果是文本那么转化成span标签 _extractcontent.childNodes[0].nodeType == 3 && U.UF.E.validElement(_extractcontent)
  199. if (_extractcontent.childNodes[0] && _extractcontent.childNodes[0].nodeType != 1) {
  200. //重新创建一个新的粘贴信息
  201. _frag = $$("frag");
  202. _span = $$("span", { "style": { "cssText": _stylecsstext} }, _frag);
  203. _span.appendChild(_extractcontent);
  204. _extractcontent = _frag;
  205. }
  206. //如果选取最后一行的内容是div说明是整行的处理
  207. if (_extractcontent.childNodes[0] && _extractcontent.childNodes[0].tagName == "DIV") {
  208. //把行元素所有的元素添加到粘贴元素李
  209. for (_i = 0; _i < _extractcontent.childNodes[0].childNodes.length; _i) {
  210. //样式的设置
  211. _extractcontent.childNodes[0].childNodes[_i].style.cssText = _extractcontent.childNodes[0].style.cssText + ";" + _extractcontent.childNodes[0].childNodes[_i].style.cssText;
  212. _child[_child.length - 1].appendChild(_extractcontent.childNodes[0].childNodes[_i]);
  213. }
  214. }
  215. //否则就是内容
  216. else {
  217. _child[_child.length - 1].appendChild(_extractcontent); //将选区内容元素插入到选区最后一个节点
  218. }
  219. //第一行添加
  220. for (_i = 0; _i < el.childNodes[0].childNodes.length; _i) {
  221. _startline.appendChild(el.childNodes[0].childNodes[_i]); //设置第一行的内容为插入元素的内容
  222. }
  223. }
  224. //否则其他的情况
  225. else if (_child[0]) {
  226. //设置起始行的样式为选区孩子节点的第一个元素的样式
  227. _startline.style.cssText += " " + U.UF.E.getRemainAttr(_child[0]);
  228. //设置起始行的内容为插入元素的第一个孩子节点的内容
  229. _startline.innerHTML = _child[0].innerHTML;
  230. _focusel = _startline;
  231. }
  232. //循环中间行添加处理
  233. for (_i = 1; _i < _child.length; ) {
  234. _record.addLine.push(_child[_i].id);
  235. //循环把选区内容元素插入到临时标签中
  236. _frag.appendChild(_child[_i]);
  237. }
  238. U.selectEl(_startline.parentNode).append(_frag, 0, U.selectEl(_startline).next()[0]); //添加到选择行的后面
  239. U.UF.E.elementFocus(range, _focusel, true); //重新聚焦元素
  240. var _focusline = U.UF.E.getLineElement(_focusel);
  241. if (_focusline != _startline) {
  242. editor.editor.recordRange = range;
  243. }
  244. editor.editor.recordHTML = _focusline.outerHTML;
  245. }
  246. U.UF.E.operationNotice(_record, editor);
  247. clearTimeout(editor.editor.interval); //取消计时更新
  248. }
  249. //低版本的ie兼容
  250. else {
  251. range.pasteHTML(el.outerHTML); //添加选取文字
  252. }
  253. };
  254. /* 元素全选聚焦
  255. *
  256. * @param range {object} range光标对象
  257. * @param el {element} 编辑的元素
  258. *
  259. */
  260. U.UF.E.elementFocus = function (range, el, islast) {
  261. //html5得到光标的处理
  262. if (window.getSelection) {
  263. var _selection = window.getSelection(); //选择选取的处理
  264. range.selectNodeContents(el); //添加选取的光标
  265. _selection.removeAllRanges(); //移除所有的光标
  266. _selection.addRange(range); //把聚焦元素的光标添加进去
  267. //判断光标是否放在最后面
  268. if (islast) {
  269. range.collapse(false);
  270. }
  271. }
  272. //ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
  273. else {
  274. range.moveToElementText(el); //光标移动到指定的元素位置
  275. range.select(); //聚焦选择
  276. }
  277. };
  278. /* 创建贯标
  279. *
  280. *
  281. */
  282. U.UF.E.createRnage = function () {
  283. //html5得到光标的处理
  284. if (window.getSelection) {
  285. return document.createRange();
  286. }
  287. //ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
  288. else {
  289. return document.body.createTextRange();
  290. }
  291. }
  292. /* 初始化光标处理,要求光标必须聚焦到编辑区域里,否则这里获取就会失败
  293. *
  294. * @param win {window} 编辑的域
  295. * @return {object} 光标编辑对象
  296. *
  297. */
  298. U.UF.E.getRangeAt = function (win) {
  299. var _selection, //选取对象
  300. _range //光标对象
  301. ;
  302. win = win || window; //获取创建光标的域
  303. //html5得到光标的处理
  304. if (win.getSelection) {
  305. _selection = win.getSelection(); //获取选取对象
  306. //当获取选取中有光标的处理
  307. if (_selection.rangeCount) {
  308. _range = _selection.getRangeAt(0); //返回选区的处理
  309. }
  310. }
  311. //ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
  312. else {
  313. _selection = win.document.selection; //获取选取对象
  314. _range = _selection.createRange(); //光标对象
  315. }
  316. return _range; //光标的处理
  317. };
  318. /* 替换选区内容处理,可添加元素html代码。
  319. *
  320. * @param str {string} 需要插入的文字
  321. * @param range {object} range光标对象
  322. * @param islast {boolean} 是否聚焦到最后
  323. * @return {object} 光标编辑对象
  324. */
  325. U.UF.E.addRange = function (str, range, islast) {
  326. range = range || U.UF.E.getRangeAt(); //获取光标处理
  327. //html5得到光标的处理
  328. if (window.getSelection) {
  329. var _selection = window.getSelection(), //获取选取对象
  330. _frag = range.createContextualFragment(str); //创建选取
  331. range.deleteContents(); //移除文字
  332. _selection.removeAllRanges(); //移除选取
  333. range.insertNode(_frag); //插入需要写入的内容
  334. //判断光标是否放在最后面
  335. if (islast) {
  336. range.collapse(false);
  337. }
  338. _selection.addRange(range); //把替换的文章添加到当前指定的选取中
  339. }
  340. //ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
  341. else {
  342. range.select(); //选取聚焦
  343. range.pasteHTML(str); //添加选取文字
  344. //判断光标是否放在最后面
  345. if (islast) {
  346. range.collapse(false);
  347. }
  348. }
  349. //上面重新操作光标后,需要重新聚焦
  350. return U.UF.E.getRangeAt();
  351. };
  352. /* 在光标中获取现在聚焦的元素
  353. *
  354. * @param range {object} range光标对象
  355. */
  356. U.UF.E.getRangeElement = function (range) {
  357. //html5得到光标的处理
  358. if (range.commonAncestorContainer) {
  359. return range.commonAncestorContainer;
  360. }
  361. //ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
  362. else {
  363. //正常选择元素获取元素的处理
  364. if (range.parentElement) {
  365. return range.parentElement();
  366. }
  367. //图片无法像上面的方法一样获取元素,需要通过commonParentElement获取元素
  368. else {
  369. return range.commonParentElement();
  370. }
  371. }
  372. };
  373. /* 重新选中指定的光标
  374. *
  375. * @param range {object} range光标对象
  376. */
  377. U.UF.E.reSelectRange = function (range) {
  378. //html5得到光标的处理
  379. if (window.getSelection) {
  380. var _selection = window.getSelection(); //获取选取对象
  381. _selection.removeAllRanges(); //移除选取
  382. _selection.addRange(range); //光标重新聚焦处理
  383. }
  384. //ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
  385. else {
  386. range.select(); //选取聚焦
  387. }
  388. };
  389. /* 设置编辑样式
  390. *
  391. * @param attr {object} 给指定的光标设置样式
  392. * @param range {object} 非必传参数 range光标对象
  393. * */
  394. U.UF.E.setRangeStyle = function (attr, range, editor) {
  395. range = range || U.UF.E.getRangeAt(); //获取光标处理
  396. if (range.startContainer == range.endContainer && range.startOffset == range.endOffset) {
  397. return true;
  398. }
  399. var _i, //循环变量定义
  400. _textstyle, //记录文本样式
  401. _isdel, //是否删除
  402. _start = range.startContainer, //选区起始元素
  403. _end = range.endContainer, //选区结束元素
  404. _startoffset = range.startOffset, //开始位置
  405. _endoffset = range.endOffset, //结束位置
  406. _startline = U.UF.E.getLineElement(_start), //获取选区起始行元素
  407. _endline = U.UF.E.getLineElement(_end), //获取选区结束行元素
  408. _frag = $$("frag") //创建临时元素 用于做记录d
  409. ;
  410. editor = editor || _startline.parentNode; //编辑区域元素
  411. if (!editor.editor) { return; }
  412. var _record = U.UF.E.getUpdateLine(_startline, _endline, editor); //得到修改记录
  413. //判断是否选区在同一行
  414. if (_startline != _endline) {
  415. //不同行处理
  416. var _rangselect = range.extractContents().childNodes; //获取选区的所有元素
  417. //记录新选区的起始元素
  418. _start = _rangselect[0].childNodes[0];
  419. //记录文字装饰样式
  420. _textstyle = attr["text-decoration"] || attr["textDecoration"];
  421. //第一行样式设置
  422. U.UF.E.setStyle(attr, _rangselect[0], true);
  423. if (attr.cssText == "") {
  424. _startline.style.cssText = "";
  425. }
  426. //设置样式后的元素循环添加到第一行中
  427. while (_rangselect[0].childNodes[0]) {
  428. _startline.appendChild(_rangselect[0].childNodes[0]);
  429. }
  430. //如果存在文字装饰样式
  431. if (_textstyle) {
  432. //标记设置的样式中是否已存在 存在为1 不存在为 0
  433. _isdel = (attr["text-decoration"] || attr["textDecoration"] || "").indexOf(_textstyle) > -1 ? 1 : 0;
  434. attr["text-decoration"] = _textstyle;
  435. }
  436. //循环除第一行和最后一行的每一行的处理
  437. for (_i = 1; _i < _rangselect.length - 1; ) {
  438. //设置每一行的样式
  439. U.UF.E.setStyle(attr, _rangselect[_i], _isdel);
  440. if (_textstyle) {
  441. attr["text-decoration"] = _textstyle;
  442. }
  443. if (attr.cssText == "") {
  444. _rangselect[_i].style.cssText = "";
  445. }
  446. //追加到临时标签中
  447. _frag.appendChild(_rangselect[_i]);
  448. }
  449. //最后一行样式设置
  450. U.UF.E.setStyle(attr, _rangselect[_rangselect.length - 1], _isdel);
  451. //获取选区最后一行元素
  452. var _end = _rangselect[_rangselect.length - 1].childNodes[_rangselect[_rangselect.length - 1].childNodes.length - 1];
  453. //设置样式后的元素循环添加到最后一行中
  454. while (_rangselect[_rangselect.length - 1].childNodes[0]) {
  455. U.selectEl(_endline).append(_rangselect[_rangselect.length - 1].childNodes[_rangselect[_rangselect.length - 1].childNodes.length - 1], 0, _endline.firstChild);
  456. }
  457. if (attr.cssText == "") {
  458. _endline.style.cssText = "";
  459. }
  460. range.insertNode(_frag); //插入需要写入的内容
  461. U.UF.E.setRange(_start, _end || _start, 0, 1, range); //设置选区 重新聚焦
  462. }
  463. //同行处理
  464. //同行且选择的父级为块级元素
  465. else if (_start == _end && (_start.parentNode.tagName.toLowerCase() == "span" || _start.parentNode.tagName.toLowerCase() == "a")) {
  466. var _parentspan = _start.parentNode; //获取起始标签的上级元素
  467. var _tagname = _parentspan.tagName.toLowerCase() == "a" ? "a" : "span"; //判断创建的块级元素TagName
  468. var _startsplitel = U.UF.E.splitText(_start, _startoffset); //将起始标签拆分成新的起始文本标签 返回剩余的标签
  469. var _endsplitel = U.UF.E.splitText(_startsplitel, _endoffset - _startoffset); //在剩余标签中拆分成选中和结束两块文本标签
  470. //如果第一个文本标签存在内容则创建新的span标签
  471. if (_start.data) {
  472. //创建新的span标签 该标签为起始span标签(选区前的span标签)
  473. var _span = $$(_tagname, {
  474. "style": { "cssText": U.UF.E.getRemainAttr(_parentspan) },
  475. "innerHTML": _start.data
  476. });
  477. //如果为a标签则设置href属性
  478. if (_tagname == "a") {
  479. _span.href = _parentspan.href;
  480. }
  481. //替换起始文本标签为起始span标签
  482. _parentspan.replaceChild(_span, _start);
  483. }
  484. //创建新的块级元素 该标签为选区的span标签
  485. var _rangspan = $$(_tagname, {
  486. "style": { "cssText": U.UF.E.getRemainAttr(_parentspan) },
  487. "innerHTML": _startsplitel.data
  488. });
  489. //处理样式后进行设置块级元素中
  490. U.selectEl(_rangspan).css(U.UF.E.setSpecialAttr(_rangspan, attr));
  491. //如果为a标签则设置href属性
  492. if (_tagname == "a") {
  493. _rangspan.href = _parentspan.href;
  494. }
  495. //替换选区文本标签为选区span标签
  496. _parentspan.replaceChild(_rangspan, _startsplitel);
  497. //如果结束文本标签存在内容则创建新的span标签
  498. if (_endsplitel.data) {
  499. //创建新的span标签 该标签为结束span标签(选区后的span标签)
  500. var _span1 = $$(_tagname, {
  501. "style": { "cssText": U.UF.E.getRemainAttr(_parentspan) },
  502. "innerHTML": _endsplitel.data
  503. });
  504. //如果为a标签则设置href属性
  505. if (_tagname == "a") {
  506. _span1.href = _parentspan.href;
  507. }
  508. //替换结束文本标签为结束span标签
  509. _parentspan.replaceChild(_span1, _endsplitel);
  510. }
  511. //将替换的元素追加到临时元素中
  512. for (i = 0; i < _parentspan.childNodes.length; ) {
  513. _frag.appendChild(_parentspan.childNodes[i]);
  514. }
  515. //替换原有元素为修改的元素
  516. _parentspan.parentNode.replaceChild(_frag, _parentspan);
  517. //设置选区
  518. U.UF.E.setRange(_rangspan, _rangspan, 0, _startsplitel.data ? 1 : 0, range);
  519. }
  520. //起始元素和结束元素相等 且本身就为块级元素的处理
  521. else if (_end == _start && _start.tagName && (_start.tagName.toLowerCase() == "span" || _start.tagName.toLowerCase() == "a")) {
  522. //记录原有的样式属性
  523. U.UF.E.getRemainAttr(_start);
  524. //处理样式后设置到起始元素中
  525. U.selectEl(_start).css(U.UF.E.setSpecialAttr(_start, attr));
  526. }
  527. //当行跨元素
  528. else {
  529. var _rangselect = range.extractContents(); //获取选区的所有元素
  530. U.UF.E.setStyle(attr, _rangselect, true); //直接调用设置样式函数 true表示为第一层
  531. range.insertNode(_rangselect); //将设置的元素插入到光标位置
  532. }
  533. //获取修改行的信息处理
  534. U.UF.E.operationNotice(_record, editor);
  535. };
  536. /* 设置样式
  537. *
  538. * @param startline {element} 修改样式修改行
  539. * @param endline {element} 修改样式结束行
  540. */
  541. U.UF.E.getUpdateLine = function (startline, endline, edit) {
  542. var _record = { updateLine: [] }; //记录
  543. //循环找所有影响的行
  544. while (startline) {
  545. _record.updateLine.push(startline.id); //修改行记录
  546. //向下寻找
  547. if (startline != endline) {
  548. startline = startline.nextElementSibling;
  549. }
  550. else {
  551. startline = false;
  552. }
  553. }
  554. //返回修改记录
  555. return _record;
  556. };
  557. /* 设置样式
  558. *
  559. * @param attr {object} 给指定的光标设置样式
  560. * @param el {object} 设置样式的元素
  561. * @param istop {boolean} 是否为第一层标记
  562. */
  563. U.UF.E.setStyle = function (attr, el, istop) {
  564. var _nowattr, //记录当前属性 该变量的作用主要用于记录新的样式
  565. _nowspan, //记录当前元素的span元素
  566. _newspan, //记录新的span元素
  567. _textstyle = attr["text-decoration"] || attr["textDecoration"],
  568. _span = U.UF.E.getTagNameElement(el); //获取块级元素
  569. var _spanText = _span && _span.innerHTML; //获取行级元素的innerHTML
  570. //根据内容是否相等 判断是否选择整个span标签
  571. if (_span && _spanText == el.data) {
  572. _nowattr = U.UF.E.setSpecialAttr(_span, attr); //整理特殊样式
  573. U.selectEl(_span).css(_nowattr); //设置样式
  574. }
  575. //如果设置样式的元素不为整个span标签
  576. else {
  577. var _rangselect = el.childNodes; //获取设置样式元素下的所有子级
  578. //循环给每一个子级添加样式
  579. for (var i = 0; i < _rangselect.length; i++) {
  580. //是第一层且为第一个元素是处理样式
  581. if (istop === true && !i) {
  582. U.UF.E.setSpecialAttr(_rangselect[i], attr); //设置最后需要设置的值
  583. //设置istop 设置后的功能为判断是否需要设置
  584. istop = (attr["text-decoration"] || attr["textDecoration"] || "").indexOf(_textstyle) > -1 ? 1 : 0;
  585. }
  586. //如果存在文字装饰属性
  587. if (attr["text-decoration"] || attr["textDecoration"]) {
  588. //需要添加样式的处理
  589. if (istop === 1) {
  590. //如果为元素节点且存在文字装饰属性 并且不等于inherit和node
  591. if (_rangselect[i].style && _rangselect[i].style["text-decoration"] && _rangselect[i].style["text-decoration"] != "inherit" && _rangselect[i].style["text-decoration"] != "none") {
  592. //修改设置的属性为原有样式加当前样式
  593. attr["text-decoration"] = _rangselect[i].style["text-decoration"].replace(_textstyle, "") + " " + _textstyle;
  594. }
  595. //否则则直接设置为当前样式
  596. else {
  597. attr["text-decoration"] = _textstyle;
  598. }
  599. }
  600. //需要删除的处理
  601. else if (istop === 0) {
  602. //判断是否为元素节点
  603. //如果是元素节点
  604. if (_rangselect[i].style) {
  605. //判断是否存在当前样式
  606. //如果存在则去除当前样式
  607. if (_rangselect[i].style["text-decoration"].indexOf(_textstyle) > -1) {
  608. //去除当前样式
  609. attr["text-decoration"] = _rangselect[i].style["text-decoration"].replace(_textstyle, "");
  610. //去除完毕后如果为空则设置为inherit
  611. if (attr["text-decoration"] == "") {
  612. attr["text-decoration"] = "inherit";
  613. }
  614. }
  615. //不存在时直接替换
  616. else {
  617. attr["text-decoration"] = _rangselect[i].style["text-decoration"];
  618. }
  619. }
  620. //否则直接设置为inherit(继承父级属性)
  621. else {
  622. attr["text-decoration"] = "inherit";
  623. }
  624. }
  625. }
  626. //根据是否存在tagName(标签名) 判断是否为元素节点
  627. //如果为元素节点则直接设置样式
  628. if (_rangselect[i].tagName) {
  629. U.selectEl(_rangselect[i]).css(attr); //设置样式
  630. }
  631. //否则则创建新的span标签 并替换原有是元素
  632. else if (_rangselect[i].nodeValue) {
  633. //创建新的span标签
  634. _newspan = $$("span", {
  635. "innerHTML": _rangselect[i].nodeValue,
  636. "style": attr
  637. });
  638. //替换原有是元素
  639. _rangselect[i].parentNode.replaceChild(_newspan, _rangselect[i]);
  640. }
  641. }
  642. }
  643. };
  644. /* 特殊样式处理
  645. *
  646. * @param element {element} 被继承样式的元素
  647. * @param attr {object} 当前的样式属性
  648. */
  649. U.UF.E.setSpecialAttr = function (element, attr) {
  650. var _key, //for in 循环的key值
  651. _newvalue, //新的值
  652. _value; //当前值
  653. if (element.style) {
  654. //循环没个样式
  655. for (_key in attr) {
  656. if (attr[_key] == "") {
  657. attr[_key] = "";
  658. }
  659. else {
  660. //判断是否为文字装饰样式属性
  661. if (_key == "text-decoration" || _key == "textDecoration") {
  662. //获取当前元素该样式的值
  663. _value = element.style[_key];
  664. //获取的样式有值且不为继承属性时
  665. if (_value && _value != "inherit" && _value != 'none') {
  666. //删除样式中的属性
  667. _newvalue = _value.replace(attr[_key], "");
  668. //如果替换后为空则设置为继承
  669. if (_newvalue == "") {
  670. attr[_key] = "inherit";
  671. }
  672. //否则如果替换后的值相等则将值设置进去
  673. else if (_newvalue == _value) {
  674. attr[_key] = attr[_key] + " " + _value;
  675. }
  676. //如果不等于则设置为新的值
  677. else {
  678. attr[_key] = _newvalue;
  679. }
  680. }
  681. }
  682. //否则如果设置的样式等于原本的样式 则设置为继承属性
  683. else if (attr[_key] == element.style[_key] && "font-weight|fontWeight|font-style|fontStyle|".indexOf(_key) > -1) {
  684. attr[_key] = "inherit";
  685. }
  686. }
  687. }
  688. }
  689. //返回处理好后的属性
  690. return attr;
  691. };
  692. /* 把一个text标签进行拆分
  693. *
  694. * @param node {element} 元素节点
  695. * @param offset {number} 拆分的位置
  696. */
  697. U.UF.E.splitText = function (node, offset) {
  698. //如果拆分文字的位置等于总的长度,那么就在最后面添加空文本。
  699. if (offset == node.nodeValue.length) {
  700. var next = document.createTextNode('');
  701. U.selectEl(node.parentNode).append(next, null, node);
  702. return next;
  703. }
  704. var retval = node.splitText(offset);
  705. return retval;
  706. };
  707. /* 获取到行元素
  708. *
  709. * @param el {element} 选取元素
  710. */
  711. U.UF.E.getLineElement = function (el) {
  712. var _mel = el,
  713. _tagname = el.tagName ? el.tagName.toLowerCase() : ""; //获取元素的标签名
  714. //循环得到行元素
  715. while (el && _tagname != "body" && (_tagname != "div" || !(el.id && el.id.length == "37"))) {
  716. el = el.parentNode;
  717. if (el) {
  718. _tagname = el.tagName ? el.tagName.toLowerCase() : ""; //标签名
  719. }
  720. };
  721. return (el && el.id) ? el : null;
  722. };
  723. /* 获取到块级元素
  724. *
  725. * @param {element} 选取元素
  726. */
  727. U.UF.E.getTagNameElement = function (node, tagname) {
  728. tagname = tagname || 'span';
  729. while (node) {
  730. if (node.nodeName.toLocaleLowerCase() === tagname) {
  731. return node;
  732. } else if (node.nodeName.toLocaleLowerCase() === 'div' && !node.inline) {
  733. return null;
  734. }
  735. node = node.parentNode;
  736. }
  737. };
  738. /* 设置行的样式,如居中,局左,局右,设置编号等等功能
  739. *
  740. * @param {object} range光标对象
  741. * @param {object} 给指定的光标设置样式
  742. */
  743. U.UF.E.setLineStyle = function (style, range) {
  744. if ($('.U_UF_E_Picture_dragDot')[0]) {//清除图片拉伸的的虚拟框
  745. U.selectEl('.U_UF_E_Picture_dragDot')[0].style.display = "none";
  746. }
  747. range = range || U.UF.E.getRangeAt(); //获取光标处理
  748. var _rangeline,
  749. _start = range.startContainer
  750. _td = U.selectEl(_start).Parent({ "tagName": "TD" }); //起始选区
  751. //判断居中的元素是不是td标签
  752. if (_td && _td.tagName == "TD") {
  753. _rangeline = [_td];
  754. }
  755. else {
  756. _rangeline = U.UF.E.getRangeLineElement(range);
  757. }
  758. var i = 0; //设置循环变量
  759. for (i = 0; i < _rangeline.length; i++) { //循环设置样式
  760. U.selectEl(_rangeline[i]).css(style); //设置样式
  761. }
  762. U.UF.E.reSelectRange(range);
  763. return range; //返回选区对象
  764. };
  765. /* 获取选区行元素
  766. *
  767. * @param range {object} range光标对象
  768. * */
  769. U.UF.E.getRangeLineElement = function (range) {
  770. range = range || U.UF.E.getRangeAt(); //获取光标处理
  771. var _start = range.startContainer, //起始选区
  772. _end = range.endContainer, //结束选区
  773. _stratline = U.UF.E.getLineElement(_start), //起始选行
  774. _endline = U.UF.E.getLineElement(_end), //结束选行
  775. _nextline = U.selectEl(_stratline).next()[0], //下一行
  776. _rangeline = [_stratline]; //选中行记录
  777. if (_stratline != _endline) { //如果起始行不等于结束行则证明选择多行
  778. while (_nextline) { //循环记录选择的每一行
  779. _rangeline.push(_nextline); //添加到选择行记录中
  780. if (_nextline != _endline) { //如果依旧不等于结束行 则证明未获取完毕
  781. _nextline = U.selectEl(_nextline).next()[0]; //修改下一行变量
  782. } else { //直至等于为止
  783. _nextline = false;
  784. }
  785. }
  786. }
  787. return _rangeline;
  788. }
  789. /* 设置字体方向
  790. *
  791. * @param direction {string} 方向 left center right
  792. * */
  793. U.UF.E.textAlign = function (direction) {
  794. U.UF.E.setLineStyle({ 'text-align': direction });
  795. };
  796. /* 设置光标位置
  797. *
  798. * @param {element} 选区起始元素
  799. * @param {element} 选区结束元素
  800. * @param {number} 起始位置
  801. * @param {number} 结束位置
  802. * @param {number} 光标对象
  803. */
  804. U.UF.E.setRange = function (startel, endel, start, end, range) {
  805. range = range || U.UF.E.getRangeAt(); //获取光标处理
  806. //html5处理光标选取的处理
  807. if (window.getSelection) {
  808. //判断光标没有聚焦到制定的元素上,就无法设置焦点,这里需要处理聚焦问题。
  809. if (startel == endel && range.startContainer != startel) {
  810. range.selectNodeContents(startel); //由于位置要还原制定span标签中
  811. }
  812. range.setStart(startel, start); //设置光标开始的位置
  813. range.setEnd(endel, end); //设置光标结束的位置
  814. }
  815. //ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
  816. else {
  817. var _range1 = document.body.createTextRange(), //创建一个光标1
  818. _range2 = document.body.createTextRange(); //创建一个光标2
  819. _range1.moveToElementText(startel); //光标放在开始的地方
  820. _range1.moveStart("character", startel); //给光标设置
  821. _range2.moveToElementText(endel); //光标放在结束的地方
  822. _range2.moveStart("character", end); //设置光标结束区域的位置
  823. _range1.setEndPoint("EndToStart", _range2); //光标1和光标2接连在一起形成选取
  824. _range1.select(); //选择
  825. range = _range1;
  826. }
  827. return range;
  828. }
  829. /* 格式整理,只整理第一层和第二层
  830. *
  831. * @param el {element} 整理的内容元素
  832. */
  833. U.UF.E.unifiedFormat = function (el) {
  834. var _i, //循环
  835. _float,
  836. _tagname,
  837. _removeTagName = ['head', 'meta', 'script', 'link', 'style', 'title'], //需要移除的的标签
  838. _frag = $$("frag"), //创建临时记录内容标签
  839. _div, //行
  840. _child = el.childNodes; //获取子级,改子级全部为行
  841. //清除多余的元素
  842. U.UF.E.unifiedFormat.remove(el);
  843. //循环处理每一行
  844. for (_i = 0; _i < _child.length; _i++) {
  845. _display = _child[_i].currentStyle ? _child[_i].currentStyle.display : ""; //是否为行标签的处理
  846. _tagname = _child[_i].tagName ? _child[_i].tagName.toLowerCase() : ""; //标签名
  847. _float = _child[_i].currentStyle ? _child[_i].currentStyle.float : ""; //是否为行标签的处理
  848. //附件不进行过滤
  849. if (_child[_i].className == "U_MD_O_attachment") {
  850. U.selectEl(_child[_i]).appendTo(_frag);
  851. continue;
  852. }
  853. //行元素的处理
  854. if (!_div || (_display != "" && _display != "inline") && (_float != "left" || _float != "right")) {
  855. //所有的行标签的处理
  856. //创建行标签
  857. _div = $$("div", { "id": "e" + Guid.newGuid(), "style": { "cssText": U.UF.E.getRemainAttr(_child[_i])} }, _frag);
  858. }
  859. //调用非行元素处理函数 即不为第一层的处理
  860. U.UF.E.unifiedFormat.next(_child[_i], true, _div);
  861. if (!_div.childNodes.length && _frag.childNodes.length > 1) {
  862. U.selectEl(_div).remove();
  863. }
  864. }
  865. //返回处理后的临时元素
  866. return _frag;
  867. };
  868. /* 格式整理,过滤标签
  869. *
  870. * @param el {element} 整理的内容元素
  871. */
  872. U.UF.E.unifiedFormat.remove = function (el) {
  873. var _i, //循环
  874. _tagname, //标题名
  875. _removeTagName = ['head', 'meta', 'script', 'link', 'style', 'title'], //需要移除的的标签
  876. _child = el.childNodes; //获取子级,改子级全部为行
  877. //循环处理每一行
  878. for (_i = 0; _i < _child.length; _i++) {
  879. _tagname = _child[_i].tagName ? _child[_i].tagName.toLowerCase() : ""; //标签名
  880. //过去注释标签 nodeType为8 则为注释标签
  881. if (_child[_i].nodeType === 8 || (_child[_i].nodeType == 3 && _child[_i].data.trim() == "")) {
  882. _child[_i].remove();
  883. _i--;
  884. continue;
  885. }
  886. //删除过滤的标签
  887. if (_removeTagName.indexOf(_tagname) >= 0) {
  888. U.selectEl(_child[_i]).remove();
  889. _i--;
  890. continue;
  891. }
  892. }
  893. }
  894. /* 非第一行之后的所有内容处理
  895. *
  896. * @param el {element} 处理的元素
  897. * @param top {boolean} 是否为第二层标记 如果为第二层则所有标签直接修改为span标签 否则需要进行拆分
  898. * @return 处理后的结果集
  899. * */
  900. U.UF.E.unifiedFormat.next = function (el, top, fragel) {
  901. var _i, _j, //循环变量
  902. _float,
  903. _display, //记录元素真实的display属性 用于判断是否为行级元素
  904. _tagname, //记录元素的tagName
  905. _nowspan, //记录当前span
  906. _tdchild, //用于子级
  907. _fraga = $$("frag"),
  908. _frag = fragel, //$$("frag"), //用于记录整理后的内容的临时标签
  909. _span, //用于记录块级整理后的内容
  910. _childcsstext, //用于记录获取到的自己的样式
  911. _child = el.childNodes, //获取处理元素子级
  912. _tagname = el.tagName ? el.tagName.toLowerCase() : "",
  913. _cssText = (top.style ? top.style.cssText : "") + ";" + fragel.style.cssText + (_tagname == "img" ? "" : U.UF.E.getRemainAttr(el)); //获取处理元素的样式 用户继承当前样式使用
  914. //清除多余的元素
  915. U.UF.E.unifiedFormat.remove(el);
  916. //如果存在子级的处理
  917. if (_child.length) {
  918. //循环处理每一个子级
  919. for (_i = 0; _i < _child.length; _i++) {
  920. _span = null; //循环重新赋值
  921. //整理当前元素需继承的样式 父级样式 + 当前元素原有样式
  922. _childcsstext = _cssText + ";" + (_child[_i].tagName == "IMG" ? "" : U.UF.E.getRemainAttr(_child[_i]));
  923. _display = _child[_i].currentStyle ? _child[_i].currentStyle.display : ""; //是否为行标签的处理
  924. _float = _child[_i].currentStyle ? _child[_i].currentStyle.float : ""; //是否为行标签的处理
  925. //特殊标签添加样式
  926. //加粗
  927. if (_tagname == "b") {
  928. _childcsstext += ";font-weight: bold;";
  929. }
  930. //斜体
  931. else if (_tagname == "i") {
  932. _childcsstext += ";font-style: italic;";
  933. }
  934. //下划线
  935. else if (_tagname == "u") {
  936. _childcsstext += ";text-decoration: underline;";
  937. }
  938. //删除线
  939. else if (_tagname == "s") {
  940. _childcsstext += ";text-decoration: line-through;";
  941. }
  942. //如果是附件的处理
  943. if (el.className == "U_MD_O_attachment_wrapper") {
  944. }
  945. //如果当前标签为a标签或者top为字符串(当top为字符串时表明存在href属性需要替换为a标签)
  946. else if (_tagname == "a" || (U.UF.C.isElement(top) && top.tagName == "A")) {
  947. //重新设置top值
  948. // top = U.UF.C.isString(top) ? top : el.href;
  949. //设置name属性 用于传递使用
  950. _child[_i].name = _child[_i].name || top.name || el.name || "";
  951. //设置href属性 用于传递使用
  952. _child[_i].href = _child[_i].href || top.href || el.href;
  953. //创建a标签 并设置属性
  954. _span = $$("a", {
  955. "name": _child[_i].name,
  956. "href": _child[_i].href || "javascript:void(0)",
  957. "style": { "cssText": _childcsstext }
  958. }, _fraga);
  959. }
  960. //style样式标签处理
  961. else if (_tagname == "style") {
  962. el = U.selectEl(el).clone(true); //克隆style标签
  963. el.appendTo(_frag); //天机到临时记录标签中
  964. //创建新的行
  965. arguments[2] = _frag = fragel = $$("div", {
  966. "id": "e" + Guid.newGuid(),
  967. "style": { "cssText": _childcsstext }
  968. }, fragel.parentNode);
  969. break; //终止整个循环
  970. }
  971. //table表格标签处理 表格固定为行标签
  972. else if (_tagname == "table") {
  973. if (_frag.innerHTML) {
  974. //创建新的行标签
  975. _span = $$("div", {
  976. "id": "e" + Guid.newGuid(),
  977. "style": { "cssText": _childcsstext }
  978. }, fragel.parentNode);
  979. }
  980. else {
  981. _span = _frag;
  982. }
  983. //克隆当前表格元素
  984. el = U.selectEl(el).clone(true);
  985. //将表格添加到行中
  986. el.appendTo(_span);
  987. //获取所有td节点
  988. _tdchild = U.selectEl("td", el[0]);
  989. //循环保存td节点的内容 过滤表格内的样式
  990. for (_j = 0; _j < _tdchild.length; _j++) {
  991. _tdchild[_j].innerHTML = _tdchild[_j].innerText;
  992. }
  993. //创建新的行
  994. arguments[2] = _frag = fragel = $$("div", {
  995. "id": "e" + Guid.newGuid(),
  996. "style": { "cssText": _childcsstext }
  997. }, fragel.parentNode);
  998. break; //终止整个循环
  999. }
  1000. //行元素的处理
  1001. else if ((_display != "" && _display != "inline") && (_float != "left" || _float != "right") && _child[_i].innerHTML.trim() != "") {
  1002. if (_frag.innerHTML) {
  1003. //创建新的行
  1004. arguments[2] = _frag = fragel = $$("div", {
  1005. "id": "e" + Guid.newGuid(),
  1006. "style": { "cssText": _childcsstext }
  1007. }, fragel.parentNode);
  1008. }
  1009. else {
  1010. fragel.style.cssText += _childcsstext;
  1011. }
  1012. }
  1013. //否则则为块级元素
  1014. else {
  1015. _span = $$("span", { "style": { "cssText": _childcsstext} }, _fraga);
  1016. }
  1017. //进入判断是否依然存在子级 直到处理所有元素为止
  1018. var _nowspan = U.UF.E.unifiedFormat.next(_child[_i], _span || top, fragel);
  1019. //如果span元素的处理,说明下面只有文本元素的处理
  1020. if (_span) {
  1021. if (_nowspan.children.length) {
  1022. //替换记录标签中的块级标签元素
  1023. _fraga.replaceChild(_nowspan, _span);
  1024. _frag.appendChild(_fraga);
  1025. }
  1026. //如果有下级元素的处理
  1027. else if (_nowspan.childNodes.length) {
  1028. _span.appendChild(_nowspan);
  1029. _frag.appendChild(_fraga);
  1030. }
  1031. else {
  1032. U.selectEl(_span).remove();
  1033. }
  1034. }
  1035. else if (_nowspan) {
  1036. //替换记录标签中的块级标签元素
  1037. _fraga.appendChild(_nowspan);
  1038. _frag.appendChild(_fraga);
  1039. }
  1040. }
  1041. }
  1042. //如果不存在子级的处理
  1043. else {
  1044. //是否为第二层标记
  1045. if (top == true) {
  1046. if (_tagname == "img") {
  1047. var _img = U.selectEl(el).clone(true)[0];
  1048. _img.style.maxWidth = "100%";
  1049. _img.onerror = function () {
  1050. this.src = "/img/editorError.png";
  1051. this.width = 150;
  1052. this.height = 112;
  1053. }
  1054. _span = $$("span", {
  1055. "style": { "cssText": top.style.cssText }, //继承处理元素的样式
  1056. //判断是否为a标签如果是则将a标签直接记录 不是则获取内容 !!!!!!!!!注释有问题
  1057. "innerHTML": el.innerHTML != null ? el.innerHTML : el.data
  1058. });
  1059. _span.appendChild(_img);
  1060. _frag.appendChild(_span);
  1061. }
  1062. else {
  1063. //如果是则直接创建span块级标签,并添加到记录标签中
  1064. $$("span", {
  1065. "style": { "cssText": _cssText }, //继承处理元素的样式
  1066. //判断是否为a标签如果是则将a标签直接记录 不是则获取内容
  1067. "innerHTML": el.innerHTML != null ? el.innerHTML : el.data
  1068. }, _frag);
  1069. }
  1070. }
  1071. //如果不为第二层标记
  1072. else {
  1073. //且存在内容则直接创建文本节点,并添加到记录标签中
  1074. if (el.data) {
  1075. _fraga.appendChild(document.createTextNode(el.data));
  1076. }
  1077. //否则则直接克隆该元素,并添加到记录标签中 不做处理 该情况出现在img标签
  1078. else if (_tagname == "img") {
  1079. var _img = U.selectEl(el).clone(true)[0];
  1080. _img.style.maxWidth = "100%";
  1081. _img.onerror = function () {
  1082. this.src = "/img/editorError.png";
  1083. this.width = 150;
  1084. this.height = 112;
  1085. }
  1086. _span = $$("span", {
  1087. "style": { "cssText": top.style.cssText }, //继承处理元素的样式
  1088. //判断是否为a标签如果是则将a标签直接记录 不是则获取内容
  1089. "innerHTML": el.innerHTML != null ? el.innerHTML : el.data
  1090. });
  1091. _span.appendChild(_img);
  1092. _fraga.appendChild(_span);
  1093. }
  1094. }
  1095. }
  1096. //返回处理后的元素集合
  1097. return _fraga;
  1098. };
  1099. /* 获取指定的css元素 暂无使用
  1100. *
  1101. * @param ele {element} 被获取的元素
  1102. * */
  1103. U.UF.E.getRemainAttr = function (ele) {
  1104. //如果存在不存在样式 则返回空
  1105. if (!ele || !ele.style) {
  1106. return '';
  1107. }
  1108. //需要删除的属性
  1109. var _removeattr = ['position', 'width', 'height', 'background-image', 'border', 'min-height', 'float', 'min-width', 'display', 'padding', 'margin']; //
  1110. var _i; //循环变量定义
  1111. //循环将需要删除的属性的值设置为空
  1112. for (_i = 0; _i < _removeattr.length; _i++) {
  1113. //设置为空
  1114. ele.style[_removeattr[_i]] = "";
  1115. }
  1116. //返回设置后的样式
  1117. return ele.style.cssText;
  1118. };
  1119. /* 清除格式
  1120. *
  1121. * @param range {object} range光标对象
  1122. * */
  1123. U.UF.E.clearStyle = function (range) {
  1124. range = range || U.UF.E.getRangeAt(); //获取光标
  1125. var _start = range.startContainer, //选区起始元素
  1126. _end = range.endContainer, //选区结束元素
  1127. _startline = U.UF.E.getLineElement(_start), //获取选区起始行元素
  1128. _endline = U.UF.E.getLineElement(_end); //获取选区结束行元素
  1129. //同行相同的样式
  1130. if (_startline == _endline && range.toString() == _startline.innerText) {
  1131. for (var i = 0; i < _startline.childNodes.length; i++) {
  1132. if (_startline.childNodes[i].nodeName !== "#text") {
  1133. _startline.childNodes[i].style.cssText = "font-family: 微软雅黑; font-weight: normal; font-size: 10.5pt; line-height: 2;";
  1134. }
  1135. }
  1136. } else {
  1137. U.UF.E.setRangeStyle({ "cssText": "" }, range); //设置清空样式
  1138. }
  1139. U.UF.E.reSelectRange(range);
  1140. };
  1141. /* 添加超链接
  1142. *
  1143. * @param el {object} a标签对象
  1144. * @param range {object} range光标对象
  1145. * */
  1146. U.UF.E.addHref = function (el, range) {
  1147. U.selectEl("#U_UF_E_herfAlert").remove();
  1148. range = range || U.UF.E.getRangeAt(); //获取光标
  1149. var _start = range.startContainer, //获取选区起始元素
  1150. _end = range.endContainer, //获取选区结束元素
  1151. _selectel = range.cloneContents(), //获取选区的所有元素
  1152. _startline = U.UF.E.getLineElement(_start), //获取选区起始行元素
  1153. _endline = U.UF.E.getLineElement(_end); //获取选区结束行元素
  1154. el = el || U.UF.E.getTagNameElement(range.startContainer, "a");
  1155. //判断是否跨行选择
  1156. if (_startline !== _endline || U.selectEl('img', _selectel)[0]) {
  1157. //如果是则提示无法添加A标签
  1158. U.UF.UI.alertClick('选择范围横跨多个段落或存在图片,因此无法编辑');
  1159. } else {
  1160. var _box = $$('div'); //创建Confirm最大层div
  1161. if (el) {//判断是否有el
  1162. _text = el.innerHTML; //获取文本
  1163. _href = el.href; //获取超链接
  1164. var _textinput = $$('div', { innerHTML: '<span style="margin-right:7px;">文本</span>&nbsp;<input class="U_MD_O_H_Inputactive" placeholder="输入文本" value="' + _text + '" style="width:210px;height:25px;border:1px solid rgba(169,169,169,1);border-radius:2px;text-indent: 3px;" />', "style": { "line-height": "25px", "margin": "40px 41px 17px"} }, _box); //创建文本区域
  1165. var _hrefinput = $$('div', { innerHTML: '<span style="margin-right:7px;">链接</span>&nbsp;<input class="U_MD_O_H_Inputactive" placeholder="请输入网页链接地址" value="' + _href + '" style="width:210px;height:25px;border:1px solid rgba(169,169,169,1);border-radius:2px;text-indent: 3px;"/>', "style": { "margin": "0px 41px 27px", "line-height": "25px"} }, _box); //创建链接区域
  1166. U.UF.UI.confirm(_box, U.UF.C.closure(U.UF.E.addHref.confirm, [range, _hrefinput, _textinput, _text, el])); //创建Confirm
  1167. } else {
  1168. //否则执行添加A标签操作
  1169. _a = U.selectEl('a', _selectel)[0], //获取选区中的第一个a标签
  1170. _href = _a ? _a.href : '', //如果存在则已第一个a标签做为href
  1171. _text = range.toString(); //获取选区的文字
  1172. var _textinput = $$('div', { innerHTML: '<span style="margin-right:7px;">文本</span>&nbsp;<input class="U_MD_O_H_Inputactive" placeholder="输入文本" value="' + _text + '" style="width:210px;height:25px;border:1px solid rgba(169,169,169,1);border-radius:2px;text-indent: 3px;"/>', "style": { "line-height": "25px", "margin": "40px 41px 17px"} }, _box); //创建文本区域
  1173. var _hrefinput = $$('div', { innerHTML: '<span style="margin-right:7px;">链接</span>&nbsp;<input class="U_MD_O_H_Inputactive" placeholder="请输入网页链接地址" value="http://' + _href + '" style="width:210px;height:25px;border:1px solid rgba(169,169,169,1);border-radius:2px;text-indent: 3px;"/>', "style": { "margin": "0px 41px 27px", "line-height": "25px"} }, _box); //创建链接区域
  1174. U.UF.UI.confirm(_box, U.UF.C.closure(U.UF.E.addHref.confirm, [range, _hrefinput, _textinput, _text])); //创建Confirm
  1175. }
  1176. }
  1177. };
  1178. /**
  1179. * Excel确定添加A标签
  1180. * @param _cellList 为选中的单元集合
  1181. * @param hrefinput {element} 链接区域元素
  1182. * @param textinput {element} 文本区域元素
  1183. * @param text {string} 选区文本记录
  1184. */
  1185. U.UF.E.addHref.excelConfirm = function (_cellList, hrefinput, textinput, text) {
  1186. href = U.selectEl('input', hrefinput)[0].value; //获取输入的href
  1187. if (U.UF.S.Url.test(href)) { //判断链接是否合理
  1188. var _newtext = U.selectEl('input', textinput)[0].value; //获取当前文本
  1189. //被修改则直接删除选区 创建a标签直接添加
  1190. if (_cellList[0]) {
  1191. $$('a', { href: href, innerHTML: _newtext, target: "_blank" }, _cellList[0]); //创建A标签
  1192. _cellList[0].removeChild(_cellList[0].children[0]); //删除原来的文本,由创建的A标签代替
  1193. } else {
  1194. $$('a', { href: href, innerHTML: _newtext, target: "_blank" }, _cellList[0]); //创建A标签
  1195. }
  1196. }
  1197. else {
  1198. //提示链接存在有误
  1199. U.alert('输入的链接有误,无法添加');
  1200. }
  1201. };
  1202. /**
  1203. * 确定添加A标签
  1204. * @param range {object} range光标对象
  1205. * @param hrefinput {element} 链接区域元素
  1206. * @param textinput {element} 文本区域元素
  1207. * @param text {string} 选区文本记录
  1208. * @param el {object} a标签对象
  1209. */
  1210. U.UF.E.addHref.confirm = function (range, hrefinput, textinput, text, el) {
  1211. href = U.selectEl('input', hrefinput)[0].value; //获取输入的href
  1212. if (new RegExp(/http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/).test(href)) { //判断链接是否合理
  1213. var _newtext = U.selectEl('input', textinput)[0].value; //获取当前文本
  1214. var _start = range.startContainer, //获取选区起始元素
  1215. _end = range.endContainer, //获取选区起始元素
  1216. _startspan = U.UF.E.getTagNameElement(_start, 'span'),
  1217. _endspan = U.UF.E.getTagNameElement(_end, 'span');
  1218. if (el) {//判断是否有el参数(修改)
  1219. el.innerHTML = _newtext; //替换文本
  1220. el.href = href; //替换超链接
  1221. } else {
  1222. var _frag = $$('frag');
  1223. if (_newtext !== text) { //判断文本是否被修改
  1224. //被修改则直接删除选区 创建a标签直接添加
  1225. _frag = $$('a', { href: href, innerHTML: _newtext, target: "_blank" }); //创建A标签
  1226. } else {
  1227. var _selectel = range.extractContents(), //获取选区的所有元素
  1228. _rangselect = _selectel.childNodes; //获取选区的子级
  1229. var _text = _rangselect.innerHTML || _rangselect.data;
  1230. if (_newtext.trim() == "") {
  1231. $$('a', { href: href, innerHTML: href, style: { cssText: _startspan.style.cssText }, target: "_blank" }, _frag); //创建A标签
  1232. } else {
  1233. var i, _csstext;
  1234. //循环处理每一个元素
  1235. for (i = 0; i < _rangselect.length; i++) {
  1236. if (_rangselect[i].nodeType == 3) {
  1237. _csstext = i == _rangselect.length ? U.UF.E.getTagNameElement(_startspan, 'span').style.cssText : U.UF.E.getTagNameElement(_end, 'span').style.cssText;
  1238. $$("a", { href: href, innerHTML: _rangselect[i].data, style: { cssText: _csstext }, target: "_blank" }, _frag);
  1239. } else {
  1240. $$("a", { href: href, innerHTML: _rangselect[i].innerHTML, style: { cssText: _rangselect[i].style.cssText }, target: "_blank" }, _frag);
  1241. }
  1242. }
  1243. }
  1244. }
  1245. _frag = U.UF.E.unifiedFormat(_frag); //进行格式整理
  1246. _frag.firstChild.firstChild.setAttribute("target", "_blank");
  1247. if (_startspan.innerHTML == "") {
  1248. U.selectEl(_startspan).remove();
  1249. }
  1250. if (_endspan.innerHTML == "") {
  1251. U.selectEl(_startspan).remove();
  1252. }
  1253. U.UF.E.insertContent(_frag, range, U.selectEl('#U_MD_O_H_wordEditor')[0]); //调用指定位置插入内容的函数
  1254. }
  1255. }
  1256. else {
  1257. //提示链接存在有误
  1258. U.alert('输入的链接有误,无法添加');
  1259. return false;
  1260. }
  1261. };
  1262. /* 超链接点击
  1263. *
  1264. */
  1265. U.UF.E.addHref.click = function (e) {
  1266. if (document.getElementById('U_UF_E_herfAlert')) {//如果有弹框则删除
  1267. document.getElementById('U_UF_E_herfAlert').remove();
  1268. }
  1269. U.UF.EV.stopBubble(e);
  1270. var parent = U.selectEl("#U_MD_O_R_Parent")[0]; //获取编辑区
  1271. var _hyperlinkalert = $$('div', {
  1272. id: "U_UF_E_herfAlert",
  1273. style: {
  1274. "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)",
  1275. "border-radius": "2px", "line-height": "34px", "font-size": "12px", "font-family": "MicrosoftYaHei", "font-weight": "400", color: "rgba(48,126,209,1)", width: "fit-content",
  1276. width: "-webkit-fit-content", width: "-moz-fit-content", position: "absolute", zIndex: "999"
  1277. }
  1278. }, parent); //创建超链接弹框
  1279. var _link = $$('a', {
  1280. innerHTML: e.target.href,
  1281. style: {
  1282. "overflow": "hidden", "text-overflow": "ellipsis", "white-space": "nowrap", cursor: "pointer",
  1283. "max-width": "212px", "float": "left", "margin-left": "10px", "font-size": "14px"
  1284. }
  1285. }, _hyperlinkalert); //超链接按钮
  1286. var _rightButton = $$('div', { classname: "out_2", style: { "float": "right"} }, _hyperlinkalert);
  1287. var _unlink = $$('div', { innerHTML: "取消链接", style: { "float": "left", "margin-left": "20px", "margin-right": "10px", cursor: "pointer"} }, _rightButton); //取消链接按钮
  1288. var _modify = $$('div', { innerHTML: "修改", style: { "float": "left", "margin-left": "10px", "margin-right": "10px", cursor: "pointer"} }, _rightButton); //修改按钮
  1289. _link.onclick = function () {//链接的点击事件
  1290. U.UF.EV.stopBubble(e);
  1291. parent.blur();
  1292. window.open(e.target.href); //打开目标路径
  1293. }
  1294. _unlink.onclick = function () {//取消链接的点击事件
  1295. U.UF.EV.stopBubble(e);
  1296. e.target.parentElement.replaceChild($$('span', { innerText: e.target.innerText }), e.target);
  1297. _hyperlinkalert.remove(); //删除超链接弹框
  1298. parent.blur();
  1299. }
  1300. _modify.onclick = function () {//修改的点击事件
  1301. U.UF.EV.stopBubble(e);
  1302. U.UF.E.addHref(e.target); //修改弹框
  1303. parent.blur();
  1304. _hyperlinkalert.remove(); //删除超链接弹框
  1305. }
  1306. /*_hyperlinkalert.style.left = e.target.offsetLeft + "px";
  1307. _hyperlinkalert.style.top = e.target.offsetTop + 20 + "px"; //弹框的定位*/
  1308. //弹框的定位
  1309. console.log("超链接的位置", e.target.offsetLeft, e.target.offsetTop);
  1310. console.log("光标的位置", e.clientX, e.clientY);
  1311. console.log("滚动过的高度", U.selectEl('#U_MD_O_W_E_body')[0].offsetTop);
  1312. var EditorScrollTop = U.selectEl('#U_MD_O_R_Parent')[0].parentNode.scrollTop; //滚动高度
  1313. var EditorOffsetTop = U.selectEl('#U_MD_O_W_E_body')[0].offsetTop; //编辑器距窗口顶端的距离
  1314. _hyperlinkalert.style.left = e.clientX + "px";
  1315. _hyperlinkalert.style.top = e.clientY + EditorScrollTop - EditorOffsetTop + 12 + "px";
  1316. }
  1317. /* 在键盘输入的过程中处理
  1318. *
  1319. * @param editor {element} 编辑器的对象
  1320. */
  1321. U.UF.E.key = function (editor) {
  1322. editor.editor.idarr = U.UF.E.key.getLineIdArr(editor); //初始化默认的行
  1323. //将定义的//将定义的方法做为对象的onkeydown方法
  1324. editor.onkeydown = function (e) {
  1325. if (!editor.editor.recordOpera.range) {
  1326. U.UF.E.recordRangeIndex(editor); //记录range处理
  1327. }
  1328. U.UF.E.key.keyDown(e, editor);
  1329. };
  1330. //失焦处理
  1331. editor.onblur = function (e) {
  1332. U.UF.E.key.blur(e, editor);
  1333. };
  1334. //将定义的方法做为对象的onkeyup方法
  1335. editor.onkeyup = function (e) {
  1336. U.UF.E.key.keyUp(e, editor);
  1337. };
  1338. //点击事件的处理
  1339. editor.onmouseup = function (e) {
  1340. U.UF.E.key.keyUp(e, editor, true);
  1341. };
  1342. editor.onclick = function (e) {
  1343. setTimeout(function () {
  1344. U.UF.E.key.click(e, editor);
  1345. }, 0);
  1346. };
  1347. //点击记录
  1348. editor.onmousedown = function (e) {
  1349. setTimeout(function () {
  1350. U.UF.E.recordRangeIndex(editor); //记录range处理
  1351. }, 0);
  1352. };
  1353. //粘贴处理
  1354. editor.onpaste = function (e) {
  1355. var _text = U.UF.E.onpaste(e, editor); //获取text的处理
  1356. //如果text有值则不粘贴图片
  1357. if (!_text) {
  1358. U.UF.E.pasteImage(e, editor);
  1359. }
  1360. };
  1361. editor.ondragenter = U.UF.E.pasteImage.ignoreDrag;
  1362. editor.ondragover = U.UF.E.pasteImage.ignoreDrag;
  1363. editor.ondrop = U.UF.E.pasteImage.drop;
  1364. // U.selectEl(editor).bind({ });
  1365. };
  1366. /* 定义click方法
  1367. *
  1368. * @param e {event} event对象
  1369. * @param editor {element} 编辑器对象
  1370. * */
  1371. U.UF.E.key.click = function (e, edit) {
  1372. var _nowel, _range = U.UF.E.getRangeAt(), //获取处理的光标
  1373. _startel = U.UF.E.getLineElement(_range.startContainer) //开始元素
  1374. if (_startel != (_nowel = U.UF.E.getLineElement(edit.editor.recordRange.startContainer))) {
  1375. edit.editor.recordHTML = _startel.outerHTML;
  1376. }
  1377. edit.editor.recordRange = _range;
  1378. U.selectEl('#U_UF_E_herfAlert').remove();
  1379. if (e.target.tagName == "A") { //如果点击标签为A标签
  1380. if (e.ctrlKey == true) { //Ctrl键是否按下
  1381. window.open(e.target.href); //打开超链接
  1382. } else {
  1383. U.UF.E.addHref.click(e);
  1384. }
  1385. }
  1386. else if (e.target.tagName == "IMG" && e.target.offsetParent.className != "U_MD_F_D") { //如果点击的元素为图片元素,且不是好友聊天状态中
  1387. edit.imgStretch.img = e.target; //记录当前图片到拉伸对象中
  1388. U.UF.E.picture.stretch.setPosition(edit.imgStretch, e); //定位显示拉伸区域
  1389. } else {//其余情况
  1390. edit.imgStretch.stretch.style.display = "none"; //影藏拉伸框
  1391. }
  1392. }
  1393. /* 定义blur方法
  1394. *
  1395. * @param e {event} event对象
  1396. * @param editor {element} 编辑器对象
  1397. * */
  1398. U.UF.E.key.blur = function (e, edit) {
  1399. var _range = U.UF.E.getRangeAt(); //获取处理的光标
  1400. if (_range) {
  1401. var _startel = U.UF.E.getLineElement(_range.startContainer); //开始元素
  1402. _oldstartel = U.UF.E.getLineElement(edit.editor.recordRange.startContainer); //获取上一步操作所在的行
  1403. if (_startel) {
  1404. edit.editor.recordRange = _range; //记录光标对象
  1405. edit.editor.recordHTML = _startel.outerHTML; //记录内容 以此判断内容是否发送变化
  1406. edit.editor.log && console.log({ updateLine: [_startel.id] }, "在哪行失焦的");
  1407. if (_oldstartel && _oldstartel.id != "U_MD_O_H_wordEditor" && _startel == _oldstartel && _oldstartel.outerHTML != edit.editor.recordHTML) {
  1408. U.UF.E.operationNotice({ updateLine: [_startel.id] }, edit);
  1409. clearTimeout(edit.editor.interval); //取消计时更新
  1410. }
  1411. }
  1412. }
  1413. }
  1414. /* 定义onkey方法
  1415. *
  1416. * @param e {event} event对象
  1417. * */
  1418. U.UF.E.key.keyDown = function (e, edit) {
  1419. var _range = U.UF.E.getRangeAt(); //获取处理的光标
  1420. if (!_range) { return; }
  1421. var _el,
  1422. _oldstartel,
  1423. _line,
  1424. _result,
  1425. _startel = U.UF.E.getLineElement(_range.startContainer), //开始元素
  1426. _endel = U.UF.E.getLineElement(_range.endContainer); //结束元素
  1427. var _code = e.keyCode || e.which || e.charCode; //键盘码
  1428. if (_startel && _endel) {
  1429. if (e.ctrlKey || e.metaKey) {
  1430. edit.editor.recordRange = _range; //记录光标对象
  1431. switch (_code) {
  1432. case 90: //撤销(后退)
  1433. U.UF.E.key.undo(e, edit);
  1434. return;
  1435. case 89: //重做(前进)
  1436. U.UF.E.key.redo(e, edit);
  1437. return;
  1438. }
  1439. }
  1440. //判断光标是否存在的处理
  1441. clearTimeout(edit.editor.interval); //继续编辑的话直接取消计时器
  1442. //可能一直按着删除键,那么第一行给删除就添加第一行
  1443. if (edit.childNodes.length == 0) {
  1444. _result = U.UF.E.key.addDelLine(edit, _range); //删除最后一行后添加删除元素
  1445. //判断选区中是否有内容,那么就会处理删除操作
  1446. edit.editor.idarr = U.UF.E.key.getLineIdArr(edit); //获取当前文档的id集合
  1447. //记录关闭记录
  1448. edit.editor.log && console.log(_result, "内容被情况默认添加行");
  1449. //记录最新的行
  1450. edit.editor.recordRange = _range; //记录光标对象
  1451. edit.editor.recordHTML = U.UF.E.getLineElement(_range.startContainer).outerHTML; //记录内容 以此判断内容是否发送变化
  1452. //添加新行的处理
  1453. U.UF.E.operationNotice(_result, edit);
  1454. return;
  1455. }
  1456. //如果是删除行的处理
  1457. if (_code == 9) {
  1458. _range.deleteContents(); //移除文字
  1459. var _frag = $$("frag");
  1460. var _fragel = $$('div', { innerHTML: " " });
  1461. _frag.appendChild(_fragel.childNodes[0]);
  1462. U.selectEl(_fragel).remove();
  1463. _range.insertNode(_frag); //插入需要写入的内容
  1464. U.UF.E.setRange(_range.endContainer, _range.endContainer, _range.endOffset, _range.endOffset, _range); //设置选区 重新聚焦
  1465. U.UF.EV.stopDefault(); //阻止浏览器默认行为
  1466. return;
  1467. }
  1468. //回车处理
  1469. if (_code === 13) {
  1470. if (!U.UF.E.getTagNameElement(_range.commonAncestorContainer, 'table')) {
  1471. _result = U.UF.E.key.addLine(_range); //调用方法,新建行
  1472. //判断选区中是否有内容,那么就会处理删除操作
  1473. edit.editor.idarr = U.UF.E.key.getLineIdArr(edit); //获取当前文档的id集合
  1474. U.UF.EV.stopDefault(); //阻止浏览器默认行为
  1475. //记录关闭记录
  1476. edit.editor.log && console.log(_result, "更新换行的行,添加新的行");
  1477. //记录最新的行
  1478. edit.editor.recordRange = _range; //记录光标对象
  1479. edit.editor.recordHTML = U.UF.E.getLineElement(_range.startContainer).outerHTML; //记录内容 以此判断内容是否发送变化
  1480. //添加新行的处理
  1481. U.UF.E.operationNotice(_result, edit);
  1482. }
  1483. }
  1484. else {
  1485. edit.editor.recordDownHTML = _startel.outerHTML; //记录内容 以此判断内容是否发送变化
  1486. if (_startel == _endel && edit.editor.recordRange.endOffset != edit.editor.recordRange.startOffset) {
  1487. setTimeout(U.UF.C.closure(function (startel, edit) {
  1488. if (edit.editor.recordHTML != startel.outerHTML) {
  1489. var _result = { updateLine: [_startel.id] };
  1490. U.UF.E.operationNotice(_result, edit);
  1491. edit.editor.log && console.log(_result, "存在选区的输入,即时更新");
  1492. edit.editor.recordHTML = startel.outerHTML;
  1493. edit.editor.recordRange = U.UF.E.getRangeAt();
  1494. }
  1495. }, [_startel, edit]), 0);
  1496. clearTimeout(edit.editor.interval); //取消计时更新
  1497. }
  1498. _line = U.UF.E.key.getLineIdArr(edit); //获取
  1499. _result = U.UF.E.diff(_line, edit.editor.idarr); //对比得到删除的值
  1500. edit.editor.idarr = _line; //删除信息
  1501. //换行后回调的处理
  1502. if (_result.deleteLine.length) {
  1503. U.UF.E.operationNotice(_result, edit);
  1504. edit.editor.log && console.log(_result, "未松开删除按钮时,删除了行");
  1505. if (_result.updateLine[0]) {
  1506. edit.editor.recordHTML = U.selectEl("#" + _result.updateLine[0])[0].outerHTML;
  1507. edit.editor.recordRange = _range;
  1508. }
  1509. }
  1510. //没有任何特殊处理等待一点五秒的处理
  1511. else {
  1512. //普通的编辑那边等待记录,1.5秒后告诉用户修改信息
  1513. edit.editor.interval = setTimeout(function () {
  1514. if (edit.editor.recordHTML != _startel.outerHTML) {
  1515. //回调处理
  1516. U.UF.E.operationNotice({ updateLine: [_startel.id] }, edit);
  1517. edit.editor.log && console.log({ updateLine: [_startel.id] }, "超时更新行");
  1518. //记录当前的行
  1519. edit.editor.recordRange = _range; //记录光标对象
  1520. edit.editor.recordHTML = _startel.outerHTML; //记录内容 以此判断内容是否发送变化
  1521. }
  1522. }, 1000);
  1523. }
  1524. }
  1525. }
  1526. };
  1527. /* 定义键盘离开事件
  1528. *
  1529. * @param e {event} event对象
  1530. * */
  1531. U.UF.E.key.keyUp = function (e, edit, click) {
  1532. var _range = U.UF.E.getRangeAt(); //获取处理的光标
  1533. var _code = e.keyCode || e.which || e.charCode; //键盘码
  1534. if (e.ctrlKey == false) {
  1535. U.selectEl(edit).removeClass('U_MD_O_ctrlPress');
  1536. }
  1537. if (_range) {
  1538. var _line,
  1539. _result,
  1540. _oldstartel,
  1541. _startel = U.UF.E.getLineElement(_range.startContainer), //开始元素
  1542. _endel = U.UF.E.getLineElement(_range.startContainer); //结束元素
  1543. //判断第一层是否被删除掉,如果不是
  1544. if (edit.childNodes.length == 0) {
  1545. _result = U.UF.E.key.addDelLine(edit, _range); //删除最后一行后添加删除元素
  1546. //判断选区中是否有内容,那么就会处理删除操作
  1547. edit.editor.idarr = U.UF.E.key.getLineIdArr(edit); //获取当前文档的id集合
  1548. //记录关闭记录
  1549. edit.editor.log && console.log(_result, "内容被情况默认添加行");
  1550. //记录最新的行
  1551. edit.editor.recordRange = _range; //记录光标对象
  1552. edit.editor.recordHTML = U.UF.E.getLineElement(_range.startContainer).outerHTML; //记录内容 以此判断内容是否发送变化
  1553. //添加新行的处理
  1554. U.UF.E.operationNotice(_result, edit);
  1555. return;
  1556. }
  1557. _oldstartel = U.UF.E.getLineElement(edit.editor.recordRange.startContainer); //记录之前开始的行
  1558. //开始位置切换了,那么就要把开始位置作为修改行
  1559. if (_oldstartel && (_oldstartel != edit && _oldstartel != _startel || (_startel == _oldstartel && _startel.outerHTML != edit.editor.recordDownHTML))) {
  1560. if (edit.editor.recordHTML != _oldstartel.outerHTML) {
  1561. var _result = { "updateLine": [_oldstartel.id] };
  1562. U.UF.E.operationNotice(_result, edit);
  1563. edit.editor.log && console.log(_result, "光标切换且内容发送变化时");
  1564. clearTimeout(edit.editor.interval); //取消计时更新
  1565. }
  1566. edit.editor.recordRange = _range;
  1567. edit.editor.recordHTML = _startel.outerHTML;
  1568. }
  1569. if (_code > 36 && _code < 41) {
  1570. U.UF.E.recordRangeIndex(edit); //记录range处理
  1571. }
  1572. _line = U.UF.E.key.getLineIdArr(edit); //获取
  1573. _result = U.UF.E.diff(_line, edit.editor.idarr);
  1574. edit.editor.idarr = _line;
  1575. //删除行的处理
  1576. if (_result.deleteLine.length) {
  1577. U.UF.E.operationNotice(_result, edit);
  1578. edit.editor.log && console.log(_result, "删除了行");
  1579. var _range = U.UF.E.getRangeAt();
  1580. edit.editor.recordRange = _range;
  1581. edit.editor.recordHTML = U.UF.E.getLineElement(_range.commonAncestorContainer).outerHTML;
  1582. clearTimeout(edit.editor.interval); //取消计时更新
  1583. }
  1584. U.UF.E.formatBrush(edit, false); //格式刷工具未启用状态 记录当前光标所在位置的文字样式
  1585. }
  1586. };
  1587. /* 把编辑器里面的内容转换为数组,数组的id为div的id。
  1588. *
  1589. * @param edit {element} 编辑器元素
  1590. * @return 数组
  1591. * */
  1592. U.UF.E.key.getLineIdArr = function (edit) {
  1593. var _i,
  1594. _arr = [];
  1595. //循环添加子元素
  1596. for (_i = 0; _i < edit.childNodes.length; _i++) {
  1597. //判断是否是行元素,只有行元素才记录
  1598. if (edit.childNodes[_i].tagName && edit.childNodes[_i].tagName.toLowerCase() === "div") {
  1599. //记录id和innerHTML
  1600. _arr.push({ "id": edit.childNodes[_i].id, "innerHTML": edit.childNodes[_i].outerHTML });
  1601. }
  1602. }
  1603. return _arr;
  1604. };
  1605. /* 比较编辑器列删除方法
  1606. *
  1607. * @param arr 进行比较的数组一
  1608. * @param arr 进行比较的数组二
  1609. */
  1610. U.UF.E.diff = function (arr1, arr2) {
  1611. var temp = []; //临时数组1
  1612. var temparray = []; //临时数组2
  1613. var _i, _j; //循环变量
  1614. var _updateLine = [];
  1615. for (_i = 0; _i < arr1.length; _i++) {
  1616. temp[arr1[_i].id] = true; //把数组B的值当成临时数组1的键并赋值为真
  1617. }
  1618. for (_j = 0; _j < arr2.length; _j++) {
  1619. //同时把数组A的值当成临时数组1的键并判断是否为真,如果不为真说明没重复,就合并到一个新数组里,这样就可以得到一个全新并无重复的数组
  1620. if (!temp[arr2[_j].id]) {
  1621. if (_updateLine.length == 0) {
  1622. _updateLine.push(arr2[_j - 1].id);
  1623. }
  1624. temparray.push(arr2[_j].id);
  1625. }
  1626. }
  1627. return {
  1628. updateLine: _updateLine,
  1629. deleteLine: temparray
  1630. }; //返回差异值
  1631. }
  1632. /* 添加删除后的空行
  1633. *
  1634. * @param 编辑器元素
  1635. * @param range 可选
  1636. * @returns {*} 返回id
  1637. */
  1638. U.UF.E.key.addDelLine = function (edit, range) {
  1639. var _range = range || U.UF.E.getRangeAt(), //获得光标的位置
  1640. _el = $$("div", { id: edit.editor.idarr[0] ? edit.editor.idarr[0].id : "e" + Guid.newGuid(), innerHTML: "<span><br></span>" }, edit); //重新创建第一行,值为原第一行的id
  1641. _range.selectNodeContents(_el); //将光标重选中添加的内容
  1642. _range.collapse(true); //向右折叠光标选区,设置结束点和开始点相同地方
  1643. return { addLine: [_el.id] };
  1644. }
  1645. /* 添加行
  1646. *
  1647. * @param range 可选
  1648. * @returns {*} 返回id
  1649. */
  1650. U.UF.E.key.addLine = function (range) {
  1651. var _txtnode, //换行后的文本内容
  1652. _range = range || U.UF.E.getRangeAt(), //获得光标的位置
  1653. _startline = U.UF.E.getLineElement(_range.startContainer), //得到起始行的div
  1654. _el = $$('div', { id: "e" + Guid.newGuid(), style: { cssText: _startline.style.cssText} }), //需要添加的新元素
  1655. _result = {} //添加行后会影响变化的值
  1656. ;
  1657. //删除已经选中的内容
  1658. if (_range.startOffset != _range.endOffset && _range.startContainer.innerHTML !== "<br>") {
  1659. _range.deleteContents();
  1660. }
  1661. _range.setEnd(_startline, _startline.childNodes.length); //设置光标结束点的位置
  1662. _txt = _range.extractContents(); //剪切文本处理
  1663. if ($("img", _txt)[0]) {
  1664. _txtnode = _txt;
  1665. }
  1666. //判断选取是否有内容,若有返回内容,反之添加一个br标签占位
  1667. else if (_txt.textContent.trim() === '') { //如果没有内容那么就添加一个br标签
  1668. _txtnode = $$('span', { style: { cssText: (_startline.lastChild && _startline.lastChild.style) ? _startline.lastChild.style.cssText : "" }, innerHTML: "<br>" });
  1669. }
  1670. //设置内容
  1671. else {
  1672. _txtnode = _txt;
  1673. }
  1674. //如果回车行的内容为"",且没有存在有效元素 那么就记录原有样式创建默认行
  1675. if (_startline.innerText == '' && !U.UF.E.validElement(_startline)) {
  1676. var _clone = _txtnode.nodeName == "SPAN" ? _txtnode : U.selectEl('span', _txtnode)[0]; //获取可克隆样式元素
  1677. var _content = _clone ? U.selectEl(_clone).clone()[0] : $$('span', { innerHTML: "<br>" }); //创建内容
  1678. _content.innerHTML = "<br>"; //设置默认内容
  1679. U.selectEl(_content).appendTo(_startline); //追加
  1680. }
  1681. _el.appendChild(_txtnode); //添加到创建的div里面
  1682. U.UF.E.insertAfter(_el, _startline); //添加到选中的div下面
  1683. _range.selectNodeContents(_el); //将光标重选中添加的内容
  1684. _range.collapse(true); //向右折叠光标选区,设置结束点和开始点相同地方
  1685. _result.addLine = [_el.id]; //添加新的行
  1686. _result.updateLine = [_startline.id]; //结束新的行
  1687. return _result; //返回添加的id
  1688. };
  1689. /* 判断某个元素内是否存在有效元素(存在内容、存在图片等),过滤无用元素(空span)
  1690. *
  1691. * @param el {element} 父级元素
  1692. * @returns {boole} 返回是否存在有效元素
  1693. */
  1694. U.UF.E.validElement = function (el) {
  1695. var i, //定义循环变量
  1696. _children = el.children, //获取子级
  1697. _valid = false; //默认为没有有效元素
  1698. for (i = 0; i < _children.length; i++) { //循环处理
  1699. if (_children[i].nodeName == "BR") {
  1700. continue; //BR标签默认不做处理
  1701. }
  1702. else if (_children[i].nodeName == "IMG" || _children[i].innerText.length > 0 || ($('img', _children[i])[0] && _children[i].innerText.length == 0)) { //存在内容、存在图片则为有效元素
  1703. _valid = true;
  1704. }
  1705. else { //过滤无用标题
  1706. U.selectEl(_children[i]).remove();
  1707. i--;
  1708. }
  1709. }
  1710. return _valid; //返回结果
  1711. }
  1712. /* 在元素之后插入
  1713. *
  1714. * @param newEl {element} 插入的元素
  1715. * @param targetEl {element} 插入比对位置的元素
  1716. * */
  1717. U.UF.E.insertAfter = function (newEl, targetEl) {
  1718. //插入比对位置的元素的父级元素
  1719. var parentEl = targetEl.parentNode;
  1720. //如果当前元素的父级元素的最后一个元素为插入比对位置的元素
  1721. if (parentEl.lastChild === targetEl) {
  1722. //则使用appendChild直接添加到最后
  1723. parentEl.appendChild(newEl);
  1724. } else {
  1725. //否则则采用insertBefore 添加到插入比对位置的元素的上一个元素后
  1726. parentEl.insertBefore(newEl, targetEl.nextSibling);
  1727. }
  1728. //返回插入的元素
  1729. return newEl;
  1730. };
  1731. /* 复制格式
  1732. *
  1733. * 效果:把选区内的第一个或开始位置的字体样式复制,赋值到常量里
  1734. * */
  1735. U.UF.E.formatBrush = function (el, pattern) {
  1736. el = el || U.selectEl('#U_MD_O_H_wordEditor')[0];
  1737. if (U.UF.E.formatBrush.callBack && U.UF.E.formatBrush.pattern) {
  1738. U.UF.E.formatBrush.pattern = undefined;
  1739. U.selectEl(el).bind('mouseup', U.UF.E.formatBrush.callBack);
  1740. return;
  1741. }
  1742. var _style = pattern == false ? el.editor.recordRangeStyle : el.editor.brushStyle;
  1743. var range = U.UF.E.getRangeAt();
  1744. //获取选区
  1745. var _start = range.startContainer;
  1746. //选区开始位置
  1747. if (_start.nodeName == "DIV") {
  1748. //如果选区开始节点是div的话,代表添加过样式之类的
  1749. if (!range.cloneContents().children[0]) { //如果光标不能存在元素
  1750. _style = { // 情况格式刷数据
  1751. "font-family": "",
  1752. "font-size": "",
  1753. "font-weight": "",
  1754. "font-style": "",
  1755. "text-decoration": "",
  1756. "color": "",
  1757. "background-color": ""
  1758. };
  1759. pattern == false && (_style["text-align"] = "", _style["name"] = "");
  1760. return;
  1761. }
  1762. //获取选区内的第一个块状节点,的第一个文档节点
  1763. //_start = range.cloneContents().children[0].firstChild;
  1764. }
  1765. //循环常量brushstyle 刷子样式
  1766. var _value;
  1767. _start = _start.nodeType == 1 ? _start : _start.parentElement;
  1768. for (var name in _style) {
  1769. //把相应的样式名字,内容,赋值给相应的常量值
  1770. if (name == "font-size") {
  1771. _value = (parseFloat(_start.currentStyle[name]) * 72 / el.editor.dpi).toFixed(1) + "pt";
  1772. } else {
  1773. _value = _start.currentStyle[name];
  1774. }
  1775. _style[name] = _value;
  1776. }
  1777. if (pattern !== false) { //判断是否为默认记录样式处理
  1778. U.UF.E.formatBrush.pattern = pattern;
  1779. if (pattern !== true) {
  1780. U.selectEl(el).unbind("mouseup", U.UF.E.formatBrush.callBack); //是否单次取消
  1781. U.UF.E.formatBrush.callBack = function () { //设置鼠标起开处理
  1782. U.UF.E.fomatBrushNext(el); //设置样式
  1783. U.UF.E.formatBrush.pattern == undefined && U.selectEl(el).unbind("mouseup", U.UF.E.formatBrush.callBack); //是否单次取消
  1784. };
  1785. U.selectEl(el).bind('mouseup', U.UF.E.formatBrush.callBack);
  1786. }
  1787. }
  1788. else {
  1789. _style["text-align"] = U.UF.E.getLineElement(_start).currentStyle.textAlign;
  1790. _style["name"] = U.UF.E.getLineElement(_start).getAttribute('name');
  1791. U.UF.C.isFunction(el.editor.styleState) && el.editor.styleState(el.editor.recordRangeStyle);
  1792. }
  1793. };
  1794. /* 粘贴复制的样式
  1795. *
  1796. * 效果: 把常量复制到样式,粘贴到编辑器中
  1797. * */
  1798. U.UF.E.fomatBrushNext = function (el) {
  1799. U.UF.E.setRangeStyle({ "cssText": '' });
  1800. //在赋值相应的样式
  1801. U.UF.E.setRangeStyle(el.editor.brushStyle);
  1802. };
  1803. /* 附件功能
  1804. *
  1805. * @param input {element} input文件域元素
  1806. * @param editor {element} 编辑器元素
  1807. */
  1808. U.UF.E.attachment = function (input, editor) {
  1809. if (input.files.length) { //判断是否存在文件
  1810. var _range = U.UF.E.getRangeAt(); //获取光标处理
  1811. U.UF.UP.inputUpload([input], 'http://upload.1473.cn/upload', function (r) { //调用统一上传处理
  1812. var _file, _filetype, _input = r.context[0];
  1813. var _imgtype = /.*(jpg|png|gif|jpeg|JPG|PNG|GIF|JPEG|bmp|BMP)$/;
  1814. var _filearray = []; //记录上传图片的数组
  1815. if (Object.prototype.toString.call(r.value[0]) != "[object Array]") { //根据返回值类型判断是否多图上传
  1816. _filearray = [r.value]; //单图用数组则直接记录
  1817. } else {
  1818. _filearray = r.value; //多图则直接替换即可
  1819. }
  1820. var _el, _frag = $$('frag');
  1821. for (i = 0; i < _filearray.length; i++) { //循环评接拼接
  1822. _file = _input.files[i];
  1823. _filetype = _file.name.substring(_file.name.lastIndexOf('.') + 1, _file.name.length); //获取文件后缀名
  1824. if (_filetype.match(_imgtype)) {//图片类型处理
  1825. _el = $$("div", {}, _frag); ;
  1826. $$('span', { innerHTML: ' <img src="http://fs.1473.cn/' + _filearray[i][0] + '">' }, _el);
  1827. }
  1828. else { //其余文件类型处理
  1829. _el = U.UF.E.attachment.create(_file, _filearray[i][0], _filetype);
  1830. U.selectEl(_el).appendTo(_frag);
  1831. }
  1832. }
  1833. _frag = U.UF.E.unifiedFormat(_frag); //进行格式整理
  1834. U.UF.E.insertContent(_frag, _range, editor || U.selectEl('#U_MD_O_H_wordEditor')[0]); //调用指定位置插入内容的函数
  1835. }, [input]);
  1836. }
  1837. }
  1838. /* 创建附件
  1839. *
  1840. * @param input {element} input文件域元素
  1841. * @param editor {element} 编辑器元素
  1842. */
  1843. U.UF.E.attachment.create = function (file, fileinfo, type) {
  1844. //, style: { "text-align": "center"}
  1845. var _attachment = $$("div", { className: "U_MD_O_attachment", id: "e" + Guid.newGuid(), contenteditable: "false" }),
  1846. _wrapper;
  1847. var _imgtype = /.*(jpg|png|gif|jpeg|bmp)$/;
  1848. //图片类型处理
  1849. if (type.match(_imgtype)) {
  1850. $$('span', { innerHTML: ' <img src="http://fs.1473.cn/' + fileinfo[0] + '">' }, _attachment);
  1851. } else {
  1852. var _videotype = /.*(mp4|avi|wmv|ogg|webm|mpg|mpeg)$/;
  1853. var _musictype = /.*(mp3|wav|mid|midi)$/;
  1854. $$("span", { innerHTML: "&#8203;" }, _attachment);
  1855. _wrapper = $$("span", { contenteditable: "false" }, _attachment);
  1856. //音乐类型处理
  1857. if (type.match(_videotype)) {
  1858. $$('video', { src: "http://fs.1473.cn/" + fileinfo, controls: "controls", style: { "width": "530px", "height": "300px"} }, _wrapper);
  1859. }
  1860. //视频类型处理
  1861. else if (type.match(_musictype)) {
  1862. $$('audio', { src: "http://fs.1473.cn/" + fileinfo, controls: "controls" }, _wrapper);
  1863. }
  1864. //其余文件类型处理
  1865. else {
  1866. _wrapper.className = "U_MD_O_attachment_wrapper";
  1867. $$('span', { "className": "U_MD_O_attachment_wrapper_img", contenteditable: "false" }, _wrapper);
  1868. var _info = $$("span", { className: "U_MD_O_attachment_fileinfo", contenteditable: "false" }, _wrapper);
  1869. $$("span", { innerHTML: U.UF.E.attachment.fileNameSplice(file.name), contenteditable: "false" }, _info);
  1870. $$("span", { innerHTML: U.UF.C.computeFileSize(file.size), contenteditable: "false" }, _info);
  1871. $$("a", {
  1872. "href": "/Pages/Download.htm?id=" + fileinfo[2], //下载路径地址
  1873. fileid: fileinfo[2], //文件id
  1874. name: file.name, //文件名称
  1875. type: file.name.substring(file.name.lastIndexOf('.') + 1, file.name.length), //文件后缀名
  1876. target: "_blank",
  1877. innerHTML: "打开",
  1878. contenteditable: "false"
  1879. }, _wrapper);
  1880. }
  1881. $$("span", { innerHTML: "&#8203;" }, _attachment);
  1882. }
  1883. return _attachment;
  1884. }
  1885. /* 获取附件名
  1886. *
  1887. * @param input {string} 文件名字
  1888. * @param editor {number} 最大长度
  1889. */
  1890. U.UF.E.attachment.fileNameSplice = function (name, maxlength) {
  1891. maxlength = maxlength || 30;
  1892. var i, _index = 0, _gblen = 0, _start = "", _end = "";
  1893. for (i = 0; i < name.length; i++) {
  1894. if (name.charCodeAt(i) > 127 || name.charCodeAt(i) == 94) {
  1895. _gblen += 2;
  1896. } else {
  1897. _gblen++;
  1898. }
  1899. _gblen < maxlength / 2 - 2 && (_start += name[i]);
  1900. }
  1901. if (_gblen > maxlength) {
  1902. i = name.length;
  1903. while (_index < maxlength / 2 - 2) {
  1904. if (name.charCodeAt(i) > 127 || name.charCodeAt(i) == 94) {
  1905. _index += 2;
  1906. } else {
  1907. _index++;
  1908. }
  1909. _end = name[name.length - _index] + _end;
  1910. i--;
  1911. }
  1912. name = _start + "..." + _end;
  1913. }
  1914. return name;
  1915. }
  1916. /* 图片插入控件 效果:插入图片
  1917. *
  1918. * @param input {element} input文件域元素
  1919. * @param editor {element} 编辑器元素
  1920. */
  1921. U.UF.E.picture = function (input, editor) {
  1922. if (input.files.length) { //判断是否存在文件
  1923. //给最后一个input以标识,在完成上传后更改input的value值为空,解决第二次上传onchange不响应的问题。
  1924. //按道理,如果能够精准判断到谁是最后一个上传最保险,但难以判断,此做法已经生效,有问题以后再考虑。
  1925. //js上传好像是数组最后一个最先上传,所以设置第0位进行传值。
  1926. input.files[0].input = input;
  1927. for (var i = 0; i < input.files.length;i++) {
  1928. U.UF.UP.HTML5.upload("http://upload.1473.cn/upload", input.files[i], function (r) {
  1929. //document.getElementById("product_u_i_displayImg").src = "http://fs.1473.cn/" + r.fileServerName;
  1930. //如需要生成缩略图,则调用
  1931. //调用上传图片控件
  1932. var _img = ''; //设置img元素字符串
  1933. //for (i = 0; i < _imgarray.length; i++) { //循环评接拼接
  1934. // $$("span", { innerHTML: "&#8203;" }, _attachment);
  1935. _img += '<span> <img src="http://fs.1473.cn/' + r.fileServerName + '"> </span>'; //图片元素拼接
  1936. //}
  1937. //$('#U_MD_O_H_wordEditor')[0],为什么要用或者?并且多条语句连写调试好困难,需要分开。
  1938. //找到编辑器
  1939. var _editor = editor || U.selectEl('#U_MD_O_H_wordEditor')[0];
  1940. U.UF.E.textFormat(_img, _editor); //生成img元素
  1941. //获取input控件,清空其值,解决第二次上传onchange不触发的问题。
  1942. var _input = r.input;
  1943. if (_input) {
  1944. _input.value = "";
  1945. }
  1946. }, function (r) { }, function (r) { });
  1947. }
  1948. }
  1949. }
  1950. // U.UF.E.picture = function (input, editor) {
  1951. // if (input.files.length) { //判断是否存在文件
  1952. // var _range = U.UF.E.getRangeAt(); //获取光标处理
  1953. // U.UF.UP.inputUpload([input], 'http://upload.1473.cn/upload', function (r) { //调用统一上传处理
  1954. // var _input = r.context[0];
  1955. // var _imgarray = []; //记录上传图片的数组
  1956. // if (Object.prototype.toString.call(r.value[0]) != "[object Array]") { //根据返回值类型判断是否多图上传
  1957. // _imgarray = [r.value]; //单图用数组则直接记录
  1958. // } else {
  1959. // _imgarray = r.value; //多图则直接替换即可
  1960. // }
  1961. // //调用上传图片控件
  1962. // var _img = ''; //设置img元素字符串
  1963. // for (i = 0; i < _imgarray.length; i++) { //循环评接拼接
  1964. // // $$("span", { innerHTML: "&#8203;" }, _attachment);
  1965. // _img += '<span> <img src="http://fs.1473.cn/' + _imgarray[i][0] + '"> </span>'; //图片元素拼接
  1966. // }
  1967. // //$('#U_MD_O_H_wordEditor')[0],为什么要用或者?并且多条语句连写调试好困难,需要分开。
  1968. // //找到编辑器
  1969. // var _editor = editor || U.selectEl('#U_MD_O_H_wordEditor')[0];
  1970. // U.UF.E.textFormat(_img, _editor); //生成img元素
  1971. // }, [input]);
  1972. // }
  1973. // }
  1974. /* word复制粘贴图片及拖拽图片函数
  1975. *
  1976. * @param e {event} 事件对象
  1977. * @param editor {element} 编辑器元素
  1978. */
  1979. U.UF.E.pasteImage = function (e, editor) {
  1980. e.preventDefault(); //阻止默认事件
  1981. var files = e.clipboardData.files; //获取文件列表
  1982. if (files.length && e.clipboardData.types.indexOf('Files') > -1) {
  1983. var filebtn = $$('input', { type: "file" }) //新建文件域
  1984. filebtn.files = files; //获取文件列表
  1985. U.UF.E.picture(filebtn); //上传图片
  1986. filebtn.remove(); //删除文件域
  1987. }
  1988. else {
  1989. return true;
  1990. }
  1991. }
  1992. /* 阻止拖拽默认事件
  1993. *
  1994. * @param e {event} 事件对象
  1995. */
  1996. U.UF.E.pasteImage.ignoreDrag = function (e) {
  1997. //因为我们在处理拖放,所以应该确保没有其他元素会取得这个事件
  1998. e.stopPropagation();
  1999. e.preventDefault();
  2000. }
  2001. /* 拖拽上传处理
  2002. *
  2003. * @param e {event} 事件对象
  2004. */
  2005. U.UF.E.pasteImage.drop = function (e) {
  2006. //取消事件传播及默认行为
  2007. e.stopPropagation();
  2008. e.preventDefault();
  2009. //取得拖进来的文件
  2010. var data = e.dataTransfer;
  2011. var files = data.files;
  2012. //将其传给真正的处理文件的函数
  2013. var filebtn = $$('input', { type: "file" })
  2014. filebtn.files = files;
  2015. U.UF.E.picture(filebtn, this);
  2016. filebtn.remove();
  2017. }
  2018. /* 拉伸处理
  2019. *
  2020. * @param el {element} 编辑器元素
  2021. */
  2022. U.UF.E.picture.stretch = function (el) {
  2023. var _breadth = 12;
  2024. if (!el.imgStretch) {
  2025. var _img = $$("div", {
  2026. style: { display: "none", border: "1px dashed #535353", position: "absolute", minWidth: "30px", minHeight: "30px" }
  2027. }, document.body);
  2028. var _csstext = "width:" + _breadth + "px; height:" + _breadth + "px;position:absolute;z-index:999;background:url('/EditorImage/yuan1.png') no-repeat";
  2029. var _deviant = -_breadth / 2;
  2030. //创建虚拟框
  2031. el.imgStretch = {
  2032. //拉伸区域
  2033. stretch: _img,
  2034. //左上的按钮
  2035. nw: $$("div", { name: "nw", style: { cssText: _csstext, top: _deviant + "px", left: _deviant + "px", cursor: "nw-resize"} }, _img),
  2036. //右上的按钮
  2037. ne: $$("div", { name: "ne", style: { cssText: _csstext, top: _deviant + "px", right: _deviant + "px", cursor: "ne-resize"} }, _img),
  2038. //左下的按钮
  2039. sw: $$("div", { name: "sw", style: { cssText: _csstext, bottom: _deviant + "px", left: _deviant + "px", cursor: "sw-resize"} }, _img),
  2040. //右下的按钮
  2041. se: $$("div", { name: "se", style: { cssText: _csstext, bottom: _deviant + "px", right: _deviant + "px", cursor: "se-resize"} }, _img),
  2042. //上的按钮
  2043. n: $$("div", { name: "n", style: { cssText: _csstext, top: _deviant + "px", left: "calc(50% - " + -_deviant + "px)", cursor: "n-resize"} }, _img),
  2044. //下的按钮
  2045. s: $$("div", { name: "s", style: { cssText: _csstext, bottom: _deviant + "px", left: "calc(50% - " + -_deviant + "px)", cursor: "s-resize"} }, _img),
  2046. //左的按钮
  2047. w: $$("div", { name: "w", style: { cssText: _csstext, left: _deviant + "px", top: "calc(50% - " + -_deviant + "px)", cursor: "w-resize"} }, _img),
  2048. //右的按钮
  2049. e: $$("div", { name: "e", style: { cssText: _csstext, right: _deviant + "px", top: "calc(50% - " + -_deviant + "px)", cursor: "e-resize"} }, _img),
  2050. //左边的拖动虚拟线
  2051. l: $$("div", { name: "l", style: { position: "absolute", cursor: "e-resize", left: "-1px", width: "3px", height: "100%"} }, _img),
  2052. //右边的拖动虚拟线
  2053. r: $$("div", { name: "r", style: { position: "absolute", cursor: "e-resize", right: "-1px", width: "3px", height: "100%"} }, _img),
  2054. //顶部的拖动虚拟线
  2055. t: $$("div", { name: "t", style: { position: "absolute", cursor: "n-resize", top: "-1px", width: "100%", height: "3px"} }, _img),
  2056. //底部的拖动虚拟线
  2057. b: $$("div", { name: "b", style: { position: "absolute", cursor: "n-resize", bottom: "-1px", width: "100%", height: "3px"} }, _img),
  2058. maxWidth: U.selectEl(el)[0].offsetWidth
  2059. };
  2060. }
  2061. //绑定拖拽事件
  2062. new U.UF.E.picture.stretch.bindEvent(el);
  2063. };
  2064. /* 拉伸事件绑定
  2065. *
  2066. * @param el {element} 编辑器元素
  2067. */
  2068. U.UF.E.picture.stretch.bindEvent = function (el) {
  2069. this.el = el; //设置编辑器元素
  2070. this.init(); //初始化设置
  2071. }
  2072. /* 拖拽方法
  2073. *
  2074. */
  2075. U.UF.E.picture.stretch.bindEvent.prototype = {
  2076. //初始化
  2077. init: function () {
  2078. for (key in this.el.imgStretch) { //绑定所有可拉伸区域事件
  2079. key !== "stretch" && key !== "maxWidth" && this.el.imgStretch[key].addEventListener('mousedown', this.mouseDown.bind(this)); //绑定事件
  2080. }
  2081. document.body.addEventListener('mousemove', this.mouseMove.bind(this)); //绑定事件
  2082. document.body.addEventListener('mouseup', this.mouseUp.bind(this)); //绑定事件
  2083. },
  2084. //鼠标按下事件
  2085. mouseDown: function (e) {
  2086. this.name = e.target.name; //记录元素标识
  2087. this.stratX = e.clientX; //起始位置X
  2088. this.stratY = e.clientY; //起始位置Y
  2089. this.down = true; //按下标识
  2090. },
  2091. //鼠标移动事件
  2092. mouseMove: function (e) {
  2093. if (this.down) { //如果鼠标按下
  2094. //计算移动的坐标距离
  2095. var _moveX = e.clientX - this.stratX;
  2096. var _moveY = this.stratY - e.clientY;
  2097. var _click = this.name; //获取点击名称
  2098. //判断是否可以拉伸
  2099. window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
  2100. //清空移动的数据
  2101. if (_click.length == 2 || _click == "w" || _click == "e" || _click == "l" || _click == "r") {
  2102. //如果是右方的拖动就移动距离相反
  2103. (_click == "w" || _click == "sw" || _click == "nw" || _click == "l") && (_moveX = -_moveX);
  2104. //处理虚拟框的宽高,和圆圈位置
  2105. U.UF.E.picture.stretch.moveX(this.el, this.el.imgStretch, _moveX);
  2106. }
  2107. if (_click.length == 2 || _click == "n" || _click == "s" || _click == "t" || _click == "b") {
  2108. //如果是上方的拖动就移动距离相反
  2109. (_click == "n" || _click == "nw" || _click == "ne" || _click == "t") && (_moveY = -_moveY)
  2110. //处理虚拟框的宽高,和圆圈位置
  2111. U.UF.E.picture.stretch.moveY(this.el.imgStretch, _moveY);
  2112. }
  2113. //设置新的对比起始位置
  2114. this.stratX = e.clientX;
  2115. this.stratY = e.clientY;
  2116. }
  2117. },
  2118. //鼠标松开事件
  2119. mouseUp: function (e) {
  2120. if (this.down) { //如果鼠标已按下
  2121. var _imgstretch = this.el.imgStretch; //获取拉伸元素集合
  2122. _imgstretch.img.style.width = _imgstretch.stretch.offsetWidth + "px"; //赋值
  2123. _imgstretch.img.style.height = _imgstretch.stretch.offsetHeight + "px"; //赋值
  2124. U.UF.E.picture.stretch.setPosition(_imgstretch, e); //执行点击事件重新定位
  2125. this.down = false; //设置按下标识结束
  2126. }
  2127. }
  2128. }
  2129. /* 设置拉伸框位置
  2130. *
  2131. * @param obj {object} 拉伸对象
  2132. * @param event [event} 事件对象
  2133. */
  2134. U.UF.E.picture.stretch.setPosition = function (obj, event) {
  2135. var _stretch = obj.stretch; //拉伸盒子元素
  2136. var _imgel = obj.img; //被拉伸图片
  2137. //显示虚拟框,设置虚拟框的位置,大小
  2138. _stretch.style.display = "block"; //显示拉伸元素
  2139. var _imgelattr = _imgel.getBoundingClientRect(); //获取位置大小属性
  2140. if (event.clientX == event.pageX && event.clientY == event.pageY) { //当页面没有滚动时
  2141. _stretch.style.left = _imgelattr.left + "px"; //设置值
  2142. _stretch.style.top = _imgelattr.top + U.selectEl('body')[0].scrollTop + "px"; //设置值
  2143. } else {
  2144. var _offset = U.UF.E.picture.parentOfferset(_imgel, { "offsetLeft": 0, "offsetTop": 0 }); //获取父亲层的边距
  2145. _stretch.style.left = _imgel.offsetLeft + _offset.offsetLeft + parseInt($(_imgel).css("padding-left")) + "px"; //设置值
  2146. _stretch.style.top = _imgel.offsetTop + _offset.offsetTop + parseInt($(_imgel).css("padding-top")) + "px"; //设置值
  2147. }
  2148. _stretch.style.width = _imgelattr.width - 2 + "px"; //设置宽度
  2149. _stretch.style.height = _imgelattr.height - 2 + "px"; //设置高度
  2150. var _objattr = _stretch.getBoundingClientRect(); //获取位置大小属性
  2151. var _breadth = obj.n.offsetWidth / 2; //计算远点大小偏移值
  2152. obj.n.style.left = _objattr.width / 2 - _breadth + "px"; //设置顶部中心原点居中
  2153. obj.w.style.top = _objattr.height / 2 - _breadth + "px"; //设置底部中心原点居中
  2154. obj.s.style.left = _objattr.width / 2 - _breadth + "px"; //设置左部中心原点居中
  2155. obj.e.style.top = _objattr.height / 2 - _breadth + "px"; //设置右部中心原点居中
  2156. }
  2157. /* 左右拖拽方法
  2158. *
  2159. * @param el [element} 编辑器对象
  2160. * @param obj {object} 拉伸对象
  2161. * @param moveX [int} 移动距离
  2162. */
  2163. U.UF.E.picture.stretch.moveX = function (el, obj, moveX) {
  2164. var _stretch = obj.stretch; //拉伸盒子元素
  2165. if ((parseInt(_stretch.style.width) + moveX < obj.maxWidth && parseInt(_stretch.style.width) + moveX > 30)) { //判断拉伸后是否超出限制
  2166. var _align = el.editor ? el.editor.recordRangeStyle["text-align"] : ""; //获取对齐方式
  2167. switch (_align) { //判断对齐方式
  2168. case "end": //end 为 right
  2169. case "right": //居右处理
  2170. _stretch.style.left = _stretch.offsetLeft - moveX + 'px'; //设置left值
  2171. U.selectEl(_stretch)[0].style.width = parseInt(_stretch.style.width) + moveX + "px"; //设置宽度
  2172. break;
  2173. case "center": //居中处理
  2174. _stretch.style.width = parseInt(_stretch.style.width) + moveX + 'px'; //设置宽度
  2175. _stretch.style.left = parseFloat(_stretch.style.left) - moveX / 2 + 'px'; //设置偏左值
  2176. break;
  2177. default: //居左处理
  2178. _stretch.style.width = parseInt(_stretch.style.width) + moveX + "px"; //设置宽度
  2179. }
  2180. obj.n.style.left = obj.s.style.left = _stretch.offsetWidth / 2 - obj.s.offsetWidth / 2 + "px"; //设置顶部 底部原点居中
  2181. }
  2182. };
  2183. /* 上下拖拽方法
  2184. *
  2185. * @param obj {object} 拉伸对象
  2186. * @param moveX [int} 移动距离
  2187. */
  2188. U.UF.E.picture.stretch.moveY = function (obj, moveY) {
  2189. var _stretch = obj.stretch; //拉伸盒子元素
  2190. //变化虚拟框的宽度
  2191. _stretch.style.height = _stretch.offsetHeight - 2 - moveY + "px";
  2192. //变化左、右按钮的位置
  2193. obj.w.style.top = obj.e.style.top = _stretch.offsetHeight / 2 - obj.w.offsetWidth / 2 + 'px';
  2194. };
  2195. /* 得到父亲层的边距
  2196. *
  2197. * @param obj {object} 拉伸对象
  2198. * @param moveX [int} 移动距离
  2199. * @return {object} 返回父亲层的边距
  2200. */
  2201. U.UF.E.picture.parentOfferset = function (obj, json) {
  2202. var _offset = {};
  2203. //判断父亲层的左边距是否为空
  2204. if (obj.offsetParent.offsetLeft != 0) {
  2205. //如果有就赋值
  2206. _offset.offsetLeft = obj.offsetParent.offsetLeft;
  2207. } else {
  2208. //没有就赋值0
  2209. _offset.offsetLeft = 0;
  2210. }
  2211. //判断父亲层的上边距是否为空
  2212. if (obj.offsetParent.offsetTop != 0) {
  2213. //如果有就赋值
  2214. _offset.offsetTop = obj.offsetParent.offsetTop;
  2215. } else {
  2216. //没有就赋值0
  2217. _offset.offsetTop = 0;
  2218. }
  2219. json.offsetLeft = _offset.offsetLeft + json.offsetLeft;
  2220. json.offsetTop = _offset.offsetTop + json.offsetTop;
  2221. //如果 父亲层的左边距和上边距都为0 代表,没有边距了可以返回了
  2222. if (_offset.offsetTop == 0 && _offset.offsetLeft == 0) {
  2223. return json;
  2224. } else {
  2225. return U.UF.E.picture.parentOfferset(obj.offsetParent, json);
  2226. }
  2227. }
  2228. //#region 协同的处理
  2229. /*
  2230. * word 消息类
  2231. * 参数一 : id 行id
  2232. * 参数二 : type 操作类型
  2233. * 参数三 : content 行内容
  2234. * 参数四 : next 下一行
  2235. */
  2236. U.UF.E.editInfo = function (id, content, next) {
  2237. var _data = {
  2238. id: id, //操作ID
  2239. content: content, //内容
  2240. nextId: next //下一行ID
  2241. };
  2242. return _data;
  2243. };
  2244. /*
  2245. * 协同的处理
  2246. * @param e {event} event对象
  2247. * @param e {element} 编辑器对象
  2248. */
  2249. U.UF.E.operationNotice = function (operaRecord, editor) {
  2250. var _opera = {}; //记录操作记录
  2251. //是否有添加行的处理
  2252. if (operaRecord.addLine) {
  2253. _opera.addLine = U.UF.E.addLineMessage(operaRecord.addLine, editor); //得到操作行的协同记录
  2254. }
  2255. //是否有修改行的处理
  2256. if (operaRecord.updateLine) {
  2257. _opera.updateLine = U.UF.E.updateLineMessage(operaRecord.updateLine, editor); //得到修改行的协同记录
  2258. }
  2259. //是否有删除行的处理
  2260. if (operaRecord.deleteLine) {
  2261. _opera.deleteLine = U.UF.E.deleteLineMessage(operaRecord.deleteLine, editor); //得到删除行的协同记录
  2262. }
  2263. //记录前进后退
  2264. U.UF.E.setRecord(operaRecord, editor);
  2265. //协同回调
  2266. if (U.UF.C.isFunction(editor.editor.operaNotice)) {
  2267. editor.editor.operaNotice(_opera);
  2268. }
  2269. }
  2270. /*
  2271. * 添加行
  2272. * @param {array} 添加行的对象
  2273. * @param {element} 编辑器对象
  2274. */
  2275. U.UF.E.addLineMessage = function (array, edit) {
  2276. var _i,
  2277. _nextlineid,
  2278. _el,
  2279. _editinfo,
  2280. _message = []
  2281. ;
  2282. //循环添加行,获取数据
  2283. for (_i = 0; _i < array.length; _i++) {
  2284. _el = U.selectEl('#' + array[_i])[0]; //获取添加行的元素
  2285. _nextlineid = (_nextlineid = U.selectEl('#' + array[_i])[0].nextElementSibling) ? _nextlineid.id : null; //判断是否有下一行有返回id ,没有返回null
  2286. _editinfo = U.UF.E.editInfo(array[_i], _el.outerHTML, _nextlineid); //初始化word信息处理
  2287. _message.push(_editinfo); //添加数据
  2288. }
  2289. return _message;
  2290. };
  2291. /*
  2292. * 修改行内容
  2293. * @param {array} 添加行的对象
  2294. * @param {element} 编辑器对象
  2295. */
  2296. U.UF.E.updateLineMessage = function (array, edit) {
  2297. var _i,
  2298. _el,
  2299. _editinfo,
  2300. _message = [];
  2301. for (_i = 0; _i < array.length; _i++) {
  2302. _el = U.selectEl('#' + array[_i])[0]; //获取修改行的信息
  2303. _editinfo = U.UF.E.editInfo(array[_i], _el.outerHTML, null); //初始化word信息处理
  2304. _message.push(_editinfo); //添加数据
  2305. }
  2306. return _message;
  2307. };
  2308. /*
  2309. * 删除行
  2310. * @param {array} 删除的行
  2311. * @param {element} 编辑器对象
  2312. */
  2313. U.UF.E.deleteLineMessage = function (array, edit) {
  2314. var _i,
  2315. _editinfo,
  2316. _message = []
  2317. ;
  2318. for (_i = 0; _i < array.length; _i++) {
  2319. _editinfo = U.UF.E.editInfo(array[_i], "", null); //初始化word信息处理
  2320. _message.push(_editinfo); //添加数据
  2321. }
  2322. return _message;
  2323. };
  2324. //#endregion
  2325. //#region 前进后退方案
  2326. /*
  2327. * 添加前进后退内容(当)
  2328. * @param {array} 添加行的对象
  2329. * @param {element} 编辑器对象
  2330. */
  2331. U.UF.E.setRecord = function (opera, editor) {
  2332. if (editor.editor.isrecord && editor.editor.recordOpera && editor.editor.recordOpera.range) {
  2333. editor.editor.recordsEditor.splice(editor.editor.recordsEditorIndex, editor.editor.recordsEditor.length - editor.editor.recordsEditorIndex);
  2334. editor.editor.recordsEditorIndex = editor.editor.recordsEditor.length;
  2335. //插入记录
  2336. editor.editor.recordsEditor.push({
  2337. "opera": opera,
  2338. "recordLine": editor.editor.recordOpera
  2339. });
  2340. editor.editor.recordsEditorIndex++;
  2341. //重新记录
  2342. editor.editor.recordOpera = { "line": U.UF.E.key.getLineIdArr(editor) };
  2343. U.UF.E.recordRangeIndex(editor);
  2344. }
  2345. editor.editor.isrecord = true;
  2346. }
  2347. /*
  2348. * 记录光标位置和内容
  2349. * @param {array} 添加行的对象
  2350. * @param {element} 编辑器对象
  2351. */
  2352. U.UF.E.recordRangeIndex = function (editor) {
  2353. //编辑器的光标处理
  2354. var _range = U.UF.E.getRangeAt(); //得到光标
  2355. if (_range) {
  2356. var _startel = U.UF.E.getLineElement(_range.startContainer), //开始行
  2357. _endel = U.UF.E.getLineElement(_range.endContainer) //结束行
  2358. ;
  2359. if (_startel && _endel) {
  2360. //开始和结束行的处理
  2361. editor.editor.recordOpera.range = {
  2362. "startid": _startel.id,
  2363. "endid": _endel.id,
  2364. "endOffset": _range.endOffset, //
  2365. "startOffset": _range.startOffset,
  2366. "start": U.UF.E.getElementByAncestorsIndex(_startel, _range.startContainer),
  2367. "end": U.UF.E.getElementByAncestorsIndex(_endel, _range.endContainer)
  2368. };
  2369. }
  2370. }
  2371. }
  2372. /*
  2373. * 记录
  2374. * @param {Element} 祖先元素
  2375. * @param {Element} 子元素
  2376. */
  2377. U.UF.E.getElementByAncestorsIndex = function (el, childel) {
  2378. var i, j, _child, _cindex;
  2379. //获取开始位置的处理
  2380. if (el !== childel) {
  2381. _child = el.childNodes;
  2382. for (i = 0; i < _child.length; i++) {
  2383. //聚焦到子元素下的处理
  2384. if (_child[i] == childel) {
  2385. _cindex = i;
  2386. break;
  2387. }
  2388. //聚焦到子子元素的处理
  2389. else if (U.UF.EL.isChild(_child[i], childel)) {
  2390. _child = _child[i].childNodes;
  2391. //循环子元素得到位置
  2392. for (j = 0; j < _child.length; j++) {
  2393. if (_child[j] == childel) {
  2394. _cindex = [i, j];
  2395. break;
  2396. }
  2397. }
  2398. }
  2399. }
  2400. }
  2401. return _cindex;
  2402. }
  2403. /* 定义撤销(后退)函数
  2404. *
  2405. * @param e {event} event对象
  2406. * @param editor {element} 编辑器对象
  2407. * */
  2408. U.UF.E.key.undo = function (e, editor) {
  2409. var i, j, k,
  2410. _info,
  2411. _operarecord = {},
  2412. _index = editor.editor.recordsEditorIndex - 1,
  2413. _record,
  2414. _line;
  2415. if (_index > -1 && editor.editor.recordsEditor.length >= _index) {
  2416. _record = editor.editor.recordsEditor[_index];
  2417. _line = _record.recordLine.line;
  2418. //如果存在记录
  2419. if (_record.recordLine) {
  2420. for (i in _record.opera) {
  2421. switch (i) {
  2422. //添加行的处理,如果是
  2423. case "addLine":
  2424. //如果是后退添加行,那么直接删除
  2425. for (j = 0; j < _record.opera[i].length; j++) {
  2426. U.UF.E.deleteEditorLine(_record.opera[i][j]);
  2427. }
  2428. break;
  2429. case "updateLine":
  2430. //如果是后退添加行,那么直接删除
  2431. for (j = 0; j < _record.opera[i].length; j++) {
  2432. U.UF.E.updateEditorLine({ "id": _record.opera[i][j], "content": U.UF.E.getLineContentById(_line, _record.opera[i][j]) });
  2433. }
  2434. break;
  2435. case "deleteLine":
  2436. //如果是后退添加行,那么直接删除
  2437. for (j = 0; j < _record.opera[i].length; j++) {
  2438. _info = U.UF.E.getLineInfoById(_line, _record.opera[i][j]); //获取行信息
  2439. U.UF.E.addEditorLine({ "nextId": _info.next ? _info.next.id : null, "content": _info.info.innerHTML }, editor); //删除后添加回信息
  2440. }
  2441. break;
  2442. }
  2443. }
  2444. U.UF.E.setRecordRange(_record.recordLine.range); //设置光标
  2445. //如果是最后的测回,那么添加一个可前进的记录
  2446. if (editor.editor.recordsEditor.length == _index + 1) {
  2447. U.UF.E.setRecord(_record.opera, editor); //重新记录
  2448. }
  2449. editor.editor.recordsEditorIndex--;
  2450. editor.editor.isrecord = false;
  2451. }
  2452. }
  2453. //取消浏览器默认事件
  2454. U.UF.EV.stopDefault();
  2455. }
  2456. /* 定义重做(前进)函数
  2457. *
  2458. * @param e {event} event对象
  2459. * @param editor {element} 编辑器对象
  2460. * */
  2461. U.UF.E.key.redo = function (e, editor) {
  2462. var i, j, k,
  2463. _info,
  2464. _operarecord = {},
  2465. _index = editor.editor.recordsEditorIndex,
  2466. _record,
  2467. _line;
  2468. if (_index > -1 && _index < editor.editor.recordsEditor.length) {
  2469. _record = editor.editor.recordsEditor[_index];
  2470. _line = _record.recordLine.line;
  2471. //如果存在记录
  2472. if (_record.recordLine) {
  2473. for (i in _record.opera) {
  2474. switch (i) {
  2475. //添加行的处理,如果是
  2476. case "addLine":
  2477. //如果是后退添加行,那么直接删除
  2478. for (j = 0; j < _record.opera[i].length; j++) {
  2479. _info = U.UF.E.getLineInfoById(_line, _record.opera[i][j]); //获取行信息
  2480. U.UF.E.addEditorLine({ "nextId": _info.next ? _info.next.id : null, "content": _info.info.innerHTML }, editor); //删除后添加回信息
  2481. }
  2482. break;
  2483. case "updateLine":
  2484. //如果是后退添加行,那么直接删除
  2485. for (j = 0; j < _record.opera[i].length; j++) {
  2486. U.UF.E.updateEditorLine({ "id": _record.opera[i][j], "content": U.UF.E.getLineContentById(_line, _record.opera[i][j]) });
  2487. }
  2488. break;
  2489. case "deleteLine":
  2490. //如果是后退添加行,那么直接删除
  2491. for (j = 0; j < _record.opera[i].length; j++) {
  2492. U.UF.E.deleteEditorLine(_record.opera[i][j]);
  2493. }
  2494. break;
  2495. }
  2496. }
  2497. U.UF.E.setRecordRange(_record.recordLine.range); //设置光标
  2498. editor.editor.isrecord = false;
  2499. editor.editor.recordsEditorIndex++;
  2500. }
  2501. }
  2502. //取消浏览器默认事件
  2503. U.UF.EV.stopDefault();
  2504. }
  2505. /* 光标聚焦
  2506. *
  2507. * @param e {object} 自定义光标对象
  2508. */
  2509. U.UF.E.setRecordRange = function (range) {
  2510. var _startel,
  2511. _start,
  2512. _endel,
  2513. _end;
  2514. //光标开始位置和开始元素的处理
  2515. if (range.startid && U.selectEl("#" + range.startid)[0]) {
  2516. _start = range.startOffset; //开始位置
  2517. //开始元素的获取
  2518. if (range.start.length) { //如果是#text标签的处理
  2519. _startel = U.selectEl("#" + range.startid)[0].childNodes[range.start[0]].childNodes[range.start[1]];
  2520. }
  2521. else { //如果是span标签的处理
  2522. _startel = U.selectEl("#" + range.startid)[0].childNodes[range.start];
  2523. }
  2524. }
  2525. //光标结束位置的处理
  2526. if (range.endid && U.selectEl("#" + range.endid)[0]) {
  2527. _end = range.endOffset; //结束的位置
  2528. //结束元素的获取
  2529. if (range.start.length) { //如果是#text标签的处理
  2530. _endel = U.selectEl("#" + range.endid)[0].childNodes[range.end[0]].childNodes[range.end[1]];
  2531. }
  2532. else {//如果是span标签的处理
  2533. _endel = U.selectEl("#" + range.endid)[0].childNodes[range.end];
  2534. }
  2535. }
  2536. //选择光区聚焦
  2537. U.UF.E.setRange(_startel, _endel, _start, _end)
  2538. }
  2539. /* 设置记录内容
  2540. *
  2541. * @param e {event} event对象
  2542. * @param editor {element} 编辑器对象
  2543. */
  2544. U.UF.E.getLineContentById = function (line, id) {
  2545. for (var i = 0; i < line.length; i++) {
  2546. if (line[i].id == id) {
  2547. return line[i].innerHTML;
  2548. }
  2549. }
  2550. return "";
  2551. }
  2552. /* 获取行信息
  2553. *
  2554. * @param e {array} 行数组
  2555. * @param editor {string} id
  2556. */
  2557. U.UF.E.getLineInfoById = function (line, id) {
  2558. for (var i = 0; i < line.length; i++) {
  2559. if (line[i].id == id) {
  2560. return { "pre": line[i - 1], "next": line[i + 1], "info": line[i] }
  2561. }
  2562. }
  2563. return null;
  2564. }
  2565. /*
  2566. * 根据操作记录撤回或者前进修改信息
  2567. * @param {object} 操作的行
  2568. */
  2569. U.UF.E.updateEditorLine = function (opera) {
  2570. //判断修改的元素是否存在
  2571. if ($('#' + opera.id)[0]) {
  2572. U.selectEl('#' + opera.id)[0].outerHTML = opera.content;
  2573. }
  2574. else {
  2575. console.log('updateError', opera.id);
  2576. }
  2577. };
  2578. /*
  2579. * 根据操作记录撤回或者前进删除信息
  2580. * @param {object} 操作的行
  2581. */
  2582. U.UF.E.deleteEditorLine = function (opera) {
  2583. //删除行的处理
  2584. U.selectEl('#' + opera.id).remove();
  2585. };
  2586. /*
  2587. * 根据操作记录撤回或者前进添加信息
  2588. * @param {object} 操作的行
  2589. * @param {element} 编辑器元素
  2590. */
  2591. U.UF.E.addEditorLine = function (opera, editor) {
  2592. editor = editor || U.selectEl('#U_MD_O_H_wordEditor')[0]; //
  2593. var _next,
  2594. _line = $$("div", {}, editor);
  2595. //判断有没有nextid,nextid是否存在
  2596. if (opera.nextId && (_next = U.selectEl('#' + opera.nextId))[0]) {
  2597. _next.Parent().insertBefore(_line, _next[0]); //有的话插入在nexid 元素前
  2598. }
  2599. U.selectEl(_line)[0].outerHTML = opera.content; //替换内容
  2600. }
  2601. //#endregion