keystrokes.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /* 处理特殊键的兼容性问题 */
  2. UE.plugins["keystrokes"] = function() {
  3. var me = this;
  4. var collapsed = true;
  5. me.addListener("keydown", function(type, evt) {
  6. var keyCode = evt.keyCode || evt.which,
  7. rng = me.selection.getRange();
  8. //处理全选的情况
  9. if (
  10. !rng.collapsed &&
  11. !(evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) &&
  12. ((keyCode >= 65 && keyCode <= 90) ||
  13. (keyCode >= 48 && keyCode <= 57) ||
  14. (keyCode >= 96 && keyCode <= 111) ||
  15. {
  16. 13: 1,
  17. 8: 1,
  18. 46: 1
  19. }[keyCode])
  20. ) {
  21. var tmpNode = rng.startContainer;
  22. if (domUtils.isFillChar(tmpNode)) {
  23. rng.setStartBefore(tmpNode);
  24. }
  25. tmpNode = rng.endContainer;
  26. if (domUtils.isFillChar(tmpNode)) {
  27. rng.setEndAfter(tmpNode);
  28. }
  29. rng.txtToElmBoundary();
  30. //结束边界可能放到了br的前边,要把br包含进来
  31. // x[xxx]<br/>
  32. if (rng.endContainer && rng.endContainer.nodeType == 1) {
  33. tmpNode = rng.endContainer.childNodes[rng.endOffset];
  34. if (tmpNode && domUtils.isBr(tmpNode)) {
  35. rng.setEndAfter(tmpNode);
  36. }
  37. }
  38. if (rng.startOffset == 0) {
  39. tmpNode = rng.startContainer;
  40. if (domUtils.isBoundaryNode(tmpNode, "firstChild")) {
  41. tmpNode = rng.endContainer;
  42. if (
  43. rng.endOffset ==
  44. (tmpNode.nodeType == 3
  45. ? tmpNode.nodeValue.length
  46. : tmpNode.childNodes.length) &&
  47. domUtils.isBoundaryNode(tmpNode, "lastChild")
  48. ) {
  49. me.fireEvent("saveScene");
  50. me.body.innerHTML = "<p>" + (browser.ie ? "" : "<br/>") + "</p>";
  51. rng.setStart(me.body.firstChild, 0).setCursor(false, true);
  52. me._selectionChange();
  53. return;
  54. }
  55. }
  56. }
  57. }
  58. //处理backspace
  59. if (keyCode == keymap.Backspace) {
  60. rng = me.selection.getRange();
  61. collapsed = rng.collapsed;
  62. if (me.fireEvent("delkeydown", evt)) {
  63. return;
  64. }
  65. var start, end;
  66. //避免按两次删除才能生效的问题
  67. if (rng.collapsed && rng.inFillChar()) {
  68. start = rng.startContainer;
  69. if (domUtils.isFillChar(start)) {
  70. rng.setStartBefore(start).shrinkBoundary(true).collapse(true);
  71. domUtils.remove(start);
  72. } else {
  73. start.nodeValue = start.nodeValue.replace(
  74. new RegExp("^" + domUtils.fillChar),
  75. ""
  76. );
  77. rng.startOffset--;
  78. rng.collapse(true).select(true);
  79. }
  80. }
  81. //解决选中control元素不能删除的问题
  82. if ((start = rng.getClosedNode())) {
  83. me.fireEvent("saveScene");
  84. rng.setStartBefore(start);
  85. domUtils.remove(start);
  86. rng.setCursor();
  87. me.fireEvent("saveScene");
  88. domUtils.preventDefault(evt);
  89. return;
  90. }
  91. //阻止在table上的删除
  92. if (!browser.ie) {
  93. start = domUtils.findParentByTagName(rng.startContainer, "table", true);
  94. end = domUtils.findParentByTagName(rng.endContainer, "table", true);
  95. if ((start && !end) || (!start && end) || start !== end) {
  96. evt.preventDefault();
  97. return;
  98. }
  99. }
  100. }
  101. //处理tab键的逻辑
  102. if (keyCode == keymap.Tab) {
  103. //不处理以下标签
  104. var excludeTagNameForTabKey = {
  105. ol: 1,
  106. ul: 1,
  107. table: 1
  108. };
  109. //处理组件里的tab按下事件
  110. if (me.fireEvent("tabkeydown", evt)) {
  111. domUtils.preventDefault(evt);
  112. return;
  113. }
  114. var range = me.selection.getRange();
  115. me.fireEvent("saveScene");
  116. for (
  117. var i = 0,
  118. txt = "",
  119. tabSize = me.options.tabSize || 4,
  120. tabNode = me.options.tabNode || "&nbsp;";
  121. i < tabSize;
  122. i++
  123. ) {
  124. txt += tabNode;
  125. }
  126. var span = me.document.createElement("span");
  127. span.innerHTML = txt + domUtils.fillChar;
  128. if (range.collapsed) {
  129. range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
  130. } else {
  131. var filterFn = function(node) {
  132. return (
  133. domUtils.isBlockElm(node) &&
  134. !excludeTagNameForTabKey[node.tagName.toLowerCase()]
  135. );
  136. };
  137. //普通的情况
  138. start = domUtils.findParent(range.startContainer, filterFn, true);
  139. end = domUtils.findParent(range.endContainer, filterFn, true);
  140. if (start && end && start === end) {
  141. range.deleteContents();
  142. range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
  143. } else {
  144. var bookmark = range.createBookmark();
  145. range.enlarge(true);
  146. var bookmark2 = range.createBookmark(),
  147. current = domUtils.getNextDomNode(bookmark2.start, false, filterFn);
  148. while (
  149. current &&
  150. !(
  151. domUtils.getPosition(current, bookmark2.end) &
  152. domUtils.POSITION_FOLLOWING
  153. )
  154. ) {
  155. current.insertBefore(
  156. span.cloneNode(true).firstChild,
  157. current.firstChild
  158. );
  159. current = domUtils.getNextDomNode(current, false, filterFn);
  160. }
  161. range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select();
  162. }
  163. }
  164. domUtils.preventDefault(evt);
  165. }
  166. //trace:1634
  167. //ff的del键在容器空的时候,也会删除
  168. if (browser.gecko && keyCode == 46) {
  169. range = me.selection.getRange();
  170. if (range.collapsed) {
  171. start = range.startContainer;
  172. if (domUtils.isEmptyBlock(start)) {
  173. var parent = start.parentNode;
  174. while (
  175. domUtils.getChildCount(parent) == 1 &&
  176. !domUtils.isBody(parent)
  177. ) {
  178. start = parent;
  179. parent = parent.parentNode;
  180. }
  181. if (start === parent.lastChild) evt.preventDefault();
  182. return;
  183. }
  184. }
  185. }
  186. /* 修复在编辑区域快捷键 (Mac:meta+alt+I; Win:ctrl+shift+I) 打不开 chrome 控制台的问题 */
  187. browser.chrome &&
  188. me.on("keydown", function(type, e) {
  189. var keyCode = e.keyCode || e.which;
  190. if (
  191. ((e.metaKey && e.altKey) || (e.ctrlKey && e.shiftKey)) &&
  192. keyCode == 73
  193. ) {
  194. return true;
  195. }
  196. });
  197. });
  198. me.addListener("keyup", function(type, evt) {
  199. var keyCode = evt.keyCode || evt.which,
  200. rng,
  201. me = this;
  202. if (keyCode == keymap.Backspace) {
  203. if (me.fireEvent("delkeyup")) {
  204. return;
  205. }
  206. rng = me.selection.getRange();
  207. if (rng.collapsed) {
  208. var tmpNode,
  209. autoClearTagName = ["h1", "h2", "h3", "h4", "h5", "h6"];
  210. if (
  211. (tmpNode = domUtils.findParentByTagName(
  212. rng.startContainer,
  213. autoClearTagName,
  214. true
  215. ))
  216. ) {
  217. if (domUtils.isEmptyBlock(tmpNode)) {
  218. var pre = tmpNode.previousSibling;
  219. if (pre && pre.nodeName != "TABLE") {
  220. domUtils.remove(tmpNode);
  221. rng.setStartAtLast(pre).setCursor(false, true);
  222. return;
  223. } else {
  224. var next = tmpNode.nextSibling;
  225. if (next && next.nodeName != "TABLE") {
  226. domUtils.remove(tmpNode);
  227. rng.setStartAtFirst(next).setCursor(false, true);
  228. return;
  229. }
  230. }
  231. }
  232. }
  233. //处理当删除到body时,要重新给p标签展位
  234. if (domUtils.isBody(rng.startContainer)) {
  235. var tmpNode = domUtils.createElement(me.document, "p", {
  236. innerHTML: browser.ie ? domUtils.fillChar : "<br/>"
  237. });
  238. rng.insertNode(tmpNode).setStart(tmpNode, 0).setCursor(false, true);
  239. }
  240. }
  241. //chrome下如果删除了inline标签,浏览器会有记忆,在输入文字还是会套上刚才删除的标签,所以这里再选一次就不会了
  242. if (
  243. !collapsed &&
  244. (rng.startContainer.nodeType == 3 ||
  245. (rng.startContainer.nodeType == 1 &&
  246. domUtils.isEmptyBlock(rng.startContainer)))
  247. ) {
  248. if (browser.ie) {
  249. var span = rng.document.createElement("span");
  250. rng.insertNode(span).setStartBefore(span).collapse(true);
  251. rng.select();
  252. domUtils.remove(span);
  253. } else {
  254. rng.select();
  255. }
  256. }
  257. }
  258. });
  259. };