keystrokes.js 9.3 KB

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