keystrokes.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. /*
  2. * 处理特殊键的兼容性问题
  3. */
  4. UE.plugins['keystrokes'] = function() {
  5. var me = this,
  6. flag = 0,
  7. keys = domUtils.keys,
  8. trans = {
  9. 'B' : 'strong',
  10. 'I' : 'em',
  11. 'FONT' : 'span'
  12. },
  13. sizeMap = [0, 10, 12, 16, 18, 24, 32, 48],
  14. listStyle = {
  15. 'OL':['decimal','lower-alpha','lower-roman','upper-alpha','upper-roman'],
  16. 'UL':[ 'circle','disc','square']
  17. };
  18. me.addListener('keydown', function(type, evt) {
  19. var keyCode = evt.keyCode || evt.which;
  20. if(this.selectAll){
  21. this.selectAll = false;
  22. if((keyCode == 8 || keyCode == 46)){
  23. me.undoManger && me.undoManger.save();
  24. //trace:1633
  25. me.body.innerHTML = '<p>'+(browser.ie ? '' : '<br/>')+'</p>';
  26. new dom.Range(me.document).setStart(me.body.firstChild,0).setCursor(false,true);
  27. me.undoManger && me.undoManger.save();
  28. //todo 对性能会有影响
  29. browser.ie && me._selectionChange();
  30. domUtils.preventDefault(evt);
  31. return;
  32. }
  33. }
  34. //处理backspace/del
  35. if (keyCode == 8 ) {//|| keyCode == 46
  36. var range = me.selection.getRange(),
  37. tmpRange,
  38. start,end;
  39. //当删除到body最开始的位置时,会删除到body,阻止这个动作
  40. if(range.collapsed){
  41. start = range.startContainer;
  42. //有可能是展位符号
  43. if(domUtils.isWhitespace(start)){
  44. start = start.parentNode;
  45. }
  46. if(domUtils.isEmptyNode(start) && start === me.body.firstChild){
  47. if(start.tagName != 'P'){
  48. p = me.document.createElement('p');
  49. me.body.insertBefore(p,start);
  50. domUtils.fillNode(me.document,p);
  51. range.setStart(p,0).setCursor(false,true);
  52. //trace:1645
  53. domUtils.remove(start);
  54. }
  55. domUtils.preventDefault(evt);
  56. return;
  57. }
  58. }
  59. if (range.collapsed && range.startContainer.nodeType == 3 && range.startContainer.nodeValue.replace(new RegExp(domUtils.fillChar, 'g'), '').length == 0) {
  60. range.setStartBefore(range.startContainer).collapse(true)
  61. }
  62. //解决选中control元素不能删除的问题
  63. if (start = range.getClosedNode()) {
  64. me.undoManger && me.undoManger.save();
  65. range.setStartBefore(start);
  66. domUtils.remove(start);
  67. range.setCursor();
  68. me.undoManger && me.undoManger.save();
  69. domUtils.preventDefault(evt);
  70. return;
  71. }
  72. //阻止在table上的删除
  73. if (!browser.ie) {
  74. start = domUtils.findParentByTagName(range.startContainer, 'table', true);
  75. end = domUtils.findParentByTagName(range.endContainer, 'table', true);
  76. if (start && !end || !start && end || start !== end) {
  77. evt.preventDefault();
  78. return;
  79. }
  80. //表格里回车,删除时,光标被定位到了p外边,导致多次删除才能到上一行,这里的处理忘记是为什么,暂时注视掉
  81. //解决trace:1966的问题
  82. // if (browser.webkit && range.collapsed && start) {
  83. // tmpRange = range.cloneRange().txtToElmBoundary();
  84. // start = tmpRange.startContainer;
  85. // debugger
  86. // if (domUtils.isBlockElm(start) && !dtd.$tableContent[start.tagName] && !domUtils.getChildCount(start, function(node) {
  87. // return node.nodeType == 1 ? node.tagName !== 'BR' : 1;
  88. // })) {
  89. //
  90. // tmpRange.setStartBefore(start).setCursor();
  91. // domUtils.remove(start, true);
  92. // evt.preventDefault();
  93. // return;
  94. // }
  95. // }
  96. }
  97. if (me.undoManger) {
  98. if (!range.collapsed) {
  99. me.undoManger.save();
  100. flag = 1;
  101. }
  102. }
  103. }
  104. //处理tab键的逻辑
  105. if (keyCode == 9) {
  106. range = me.selection.getRange();
  107. me.undoManger && me.undoManger.save();
  108. for (var i = 0,txt = '',tabSize = me.options.tabSize|| 4,tabNode = me.options.tabNode || '&nbsp;'; i < tabSize; i++) {
  109. txt += tabNode;
  110. }
  111. var span = me.document.createElement('span');
  112. span.innerHTML = txt;
  113. if (range.collapsed) {
  114. var li = domUtils.findParentByTagName(range.startContainer, 'li', true);
  115. if (li && domUtils.isStartInblock(range)) {
  116. bk = range.createBookmark();
  117. var parentLi = li.parentNode,
  118. list = me.document.createElement(parentLi.tagName);
  119. var index = utils.indexOf(listStyle[list.tagName], domUtils.getComputedStyle(parentLi, 'list-style-type'));
  120. index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
  121. domUtils.setStyle(list, 'list-style-type', listStyle[list.tagName][index]);
  122. parentLi.insertBefore(list, li);
  123. list.appendChild(li);
  124. range.moveToBookmark(bk).select()
  125. } else
  126. range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
  127. } else {
  128. //处理table
  129. start = domUtils.findParentByTagName(range.startContainer, 'table', true);
  130. end = domUtils.findParentByTagName(range.endContainer, 'table', true);
  131. if (start || end) {
  132. evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
  133. return
  134. }
  135. //处理列表 再一个list里处理
  136. start = domUtils.findParentByTagName(range.startContainer, ['ol','ul'], true);
  137. end = domUtils.findParentByTagName(range.endContainer, ['ol','ul'], true);
  138. if (start && end && start === end) {
  139. var bk = range.createBookmark();
  140. start = domUtils.findParentByTagName(range.startContainer, 'li', true);
  141. end = domUtils.findParentByTagName(range.endContainer, 'li', true);
  142. //在开始单独处理
  143. if (start === start.parentNode.firstChild) {
  144. var parentList = me.document.createElement(start.parentNode.tagName);
  145. start.parentNode.parentNode.insertBefore(parentList, start.parentNode);
  146. parentList.appendChild(start.parentNode);
  147. } else {
  148. parentLi = start.parentNode,
  149. list = me.document.createElement(parentLi.tagName);
  150. index = utils.indexOf(listStyle[list.tagName], domUtils.getComputedStyle(parentLi, 'list-style-type'));
  151. index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
  152. domUtils.setStyle(list, 'list-style-type', listStyle[list.tagName][index]);
  153. start.parentNode.insertBefore(list, start);
  154. var nextLi;
  155. while (start !== end) {
  156. nextLi = start.nextSibling;
  157. list.appendChild(start);
  158. start = nextLi;
  159. }
  160. list.appendChild(end);
  161. }
  162. range.moveToBookmark(bk).select();
  163. } else {
  164. if (start || end) {
  165. evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
  166. return
  167. }
  168. //普通的情况
  169. start = domUtils.findParent(range.startContainer, filterFn);
  170. end = domUtils.findParent(range.endContainer, filterFn);
  171. if (start && end && start === end) {
  172. range.deleteContents();
  173. range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
  174. } else {
  175. var bookmark = range.createBookmark(),
  176. filterFn = function(node) {
  177. return domUtils.isBlockElm(node);
  178. };
  179. range.enlarge(true);
  180. var bookmark2 = range.createBookmark(),
  181. current = domUtils.getNextDomNode(bookmark2.start, false, filterFn);
  182. while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
  183. current.insertBefore(span.cloneNode(true).firstChild, current.firstChild);
  184. current = domUtils.getNextDomNode(current, false, filterFn);
  185. }
  186. range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select();
  187. }
  188. }
  189. }
  190. me.undoManger && me.undoManger.save();
  191. evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
  192. }
  193. //trace:1634
  194. //ff的del键在容器空的时候,也会删除
  195. if(browser.gecko && keyCode == 46){
  196. range = me.selection.getRange();
  197. if(range.collapsed){
  198. start = range.startContainer;
  199. if(domUtils.isEmptyBlock(start)){
  200. var parent = start.parentNode;
  201. while(domUtils.getChildCount(parent) == 1 && !domUtils.isBody(parent)){
  202. start = parent;
  203. parent = parent.parentNode;
  204. }
  205. if(start === parent.lastChild)
  206. evt.preventDefault();
  207. return;
  208. }
  209. }
  210. }
  211. });
  212. me.addListener('keyup', function(type, evt) {
  213. var keyCode = evt.keyCode || evt.which;
  214. //修复ie/chrome <strong><em>x|</em></strong> 当点退格后在输入文字后会出现 <b><i>x</i></b>
  215. if (!browser.gecko && !keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {
  216. range = me.selection.getRange();
  217. if (range.collapsed) {
  218. var start = range.startContainer,
  219. isFixed = 0;
  220. while (!domUtils.isBlockElm(start)) {
  221. if (start.nodeType == 1 && utils.indexOf(['FONT','B','I'], start.tagName) != -1) {
  222. var tmpNode = me.document.createElement(trans[start.tagName]);
  223. if (start.tagName == 'FONT') {
  224. //chrome only remember color property
  225. tmpNode.style.cssText = (start.getAttribute('size') ? 'font-size:' + (sizeMap[start.getAttribute('size')] || 12) + 'px' : '')
  226. + ';' + (start.getAttribute('color') ? 'color:' + start.getAttribute('color') : '')
  227. + ';' + (start.getAttribute('face') ? 'font-family:' + start.getAttribute('face') : '')
  228. + ';' + start.style.cssText;
  229. }
  230. while (start.firstChild) {
  231. tmpNode.appendChild(start.firstChild)
  232. }
  233. start.parentNode.insertBefore(tmpNode, start);
  234. domUtils.remove(start);
  235. if (!isFixed) {
  236. range.setEnd(tmpNode, tmpNode.childNodes.length).collapse(true)
  237. }
  238. start = tmpNode;
  239. isFixed = 1;
  240. }
  241. start = start.parentNode;
  242. }
  243. isFixed && range.select()
  244. }
  245. }
  246. if (keyCode == 8 ) {//|| keyCode == 46
  247. //针对ff下在列表首行退格,不能删除空格行的问题
  248. if(browser.gecko){
  249. for(var i=0,li,lis = domUtils.getElementsByTagName(this.body,'li');li=lis[i++];){
  250. if(domUtils.isEmptyNode(li) && !li.previousSibling){
  251. var liOfPn = li.parentNode;
  252. domUtils.remove(li);
  253. if(domUtils.isEmptyNode(liOfPn)){
  254. domUtils.remove(liOfPn)
  255. }
  256. }
  257. }
  258. }
  259. var range,start,parent,
  260. tds = this.currentSelectedArr;
  261. if (tds && tds.length > 0) {
  262. for (var i = 0,ti; ti = tds[i++];) {
  263. ti.innerHTML = browser.ie ? ( browser.version < 9 ? '&#65279' : '' ) : '<br/>';
  264. }
  265. range = new dom.Range(this.document);
  266. range.setStart(tds[0], 0).setCursor();
  267. if (flag) {
  268. me.undoManger.save();
  269. flag = 0;
  270. }
  271. //阻止chrome执行默认的动作
  272. if (browser.webkit) {
  273. evt.preventDefault();
  274. }
  275. return;
  276. }
  277. range = me.selection.getRange();
  278. //ctrl+a 后全部删除做处理
  279. //
  280. // if (domUtils.isEmptyBlock(me.body) && !range.startOffset) {
  281. // //trace:1633
  282. // me.body.innerHTML = '<p>'+(browser.ie ? '&nbsp;' : '<br/>')+'</p>';
  283. // range.setStart(me.body.firstChild,0).setCursor(false,true);
  284. // me.undoManger && me.undoManger.save();
  285. // //todo 对性能会有影响
  286. // browser.ie && me._selectionChange();
  287. // return;
  288. // }
  289. //处理删除不干净的问题
  290. start = range.startContainer;
  291. if(domUtils.isWhitespace(start)){
  292. start = start.parentNode
  293. }
  294. //标志位防止空的p无法删除
  295. var removeFlag = 0;
  296. while (start.nodeType == 1 && domUtils.isEmptyNode(start) && dtd.$removeEmpty[start.tagName]) {
  297. removeFlag = 1;
  298. parent = start.parentNode;
  299. domUtils.remove(start);
  300. start = parent;
  301. }
  302. if ( removeFlag && start.nodeType == 1 && domUtils.isEmptyNode(start)) {
  303. //ie下的问题,虽然没有了相应的节点但一旦你输入文字还是会自动把删除的节点加上,
  304. if (browser.ie) {
  305. var span = range.document.createElement('span');
  306. start.appendChild(span);
  307. range.setStart(start,0).setCursor();
  308. //for ie
  309. li = domUtils.findParentByTagName(start,'li',true);
  310. if(li){
  311. var next = li.nextSibling;
  312. while(next){
  313. if(domUtils.isEmptyBlock(next)){
  314. li = next;
  315. next = next.nextSibling;
  316. domUtils.remove(li);
  317. continue;
  318. }
  319. break;
  320. }
  321. }
  322. } else {
  323. start.innerHTML = '<br/>';
  324. range.setStart(start, 0).setCursor(false,true);
  325. }
  326. setTimeout(function() {
  327. if (browser.ie) {
  328. domUtils.remove(span);
  329. }
  330. if (flag) {
  331. me.undoManger.save();
  332. flag = 0;
  333. }
  334. }, 0)
  335. } else {
  336. if (flag) {
  337. me.undoManger.save();
  338. flag = 0;
  339. }
  340. }
  341. }
  342. })
  343. };