1 /** 2 * Add maximizeWindow/restoreWindow to Editor. 3 * @author yiminghe@gmail.com 4 */ 5 KISSY.add("editor/plugin/maximize/cmd", function (S, Editor) { 6 var UA = S.UA, 7 ie = UA['ie'], 8 doc = document, 9 Node = S.Node, 10 Event = S.Event, 11 DOM = S.DOM, 12 iframe, 13 MAXIMIZE_TOOLBAR_CLASS = "ks-editor-toolbar-padding", 14 init = function () { 15 if (!iframe) { 16 iframe = new Node("<" + "iframe " + 17 " class='ks-editor-maximize-shim'" + 18 " style='" + 19 "position:absolute;" + 20 "top:-9999px;" + 21 "left:-9999px;" + 22 "'" + 23 " frameborder='0'>").prependTo(doc.body, undefined); 24 } 25 }; 26 27 function MaximizeCmd(editor) { 28 this.editor = editor; 29 } 30 31 S.augment(MaximizeCmd, { 32 33 restoreWindow:function () { 34 var self = this, 35 editor = self.editor; 36 37 if (editor.fire("beforeRestoreWindow") === false) { 38 return; 39 } 40 41 if (self._resize) { 42 Event.remove(window, "resize", self._resize); 43 self._resize = 0; 44 } else { 45 return; 46 } 47 48 //body overflow 变化也会引起 resize 变化!!!!先去除 49 self._saveEditorStatus(); 50 self._restoreState(); 51 52 //firefox 必须timeout 53 setTimeout(function () { 54 self._restoreEditorStatus(); 55 editor.notifySelectionChange(); 56 editor.fire("afterRestoreWindow"); 57 }, 30); 58 }, 59 60 /** 61 * 从内存恢复最大化前的外围状态信息到编辑器实际动作, 62 * 包括编辑器位置以及周围元素,浏览器窗口 63 */ 64 _restoreState:function () { 65 var self = this, 66 editor = self.editor, 67 textareaEl=editor.get("textarea"), 68 //恢复父节点的position原状态 bugfix:最大化被父元素限制 69 _savedParents = self._savedParents; 70 if (_savedParents) { 71 for (var i = 0; i < _savedParents.length; i++) { 72 var po = _savedParents[i]; 73 po.el.css("position", po.position); 74 } 75 self._savedParents = null; 76 } 77 //如果没有失去焦点,重新获得当前选取元素 78 //self._saveEditorStatus(); 79 textareaEl.parent().css({ 80 height:self.iframeHeight 81 }); 82 textareaEl.css({ 83 height:self.iframeHeight 84 }); 85 DOM.css(doc.body, { 86 width:"", 87 height:"", 88 overflow:"" 89 }); 90 //documentElement 设置宽高,ie崩溃 91 doc.documentElement.style.overflow = ""; 92 93 var editorElStyle = editor.get("el")[0].style; 94 editorElStyle.position = "static"; 95 editorElStyle.width = self.editorElWidth; 96 97 /* 98 iframe 中时假死! 99 editor.editorEl.css({ 100 position:"static", 101 width:self.editorElWidth 102 });*/ 103 104 iframe.css({ 105 left:"-99999px", 106 top:"-99999px" 107 }); 108 109 window.scrollTo(self.scrollLeft, self.scrollTop); 110 111 if (ie < 8) { 112 self.editor.get("toolBarEl").removeClass(MAXIMIZE_TOOLBAR_CLASS, undefined); 113 } 114 }, 115 /** 116 * 保存最大化前的外围状态信息到内存, 117 * 包括编辑器位置以及周围元素,浏览器窗口 118 */ 119 _saveSate:function () { 120 var self = this, 121 editor = self.editor, 122 _savedParents = [], 123 editorEl = editor.get("el"); 124 self.iframeHeight = editor.get("textarea").parent().style("height"); 125 self.editorElWidth = editorEl.style("width"); 126 //主窗口滚动条也要保存哦 127 self.scrollLeft = DOM.scrollLeft(); 128 self.scrollTop = DOM.scrollTop(); 129 window.scrollTo(0, 0); 130 131 //将父节点的position都改成static并保存原状态 bugfix:最大化被父元素限制 132 var p = editorEl.parent(); 133 134 while (p) { 135 var pre = p.css("position"); 136 if (pre != "static") { 137 _savedParents.push({ 138 el:p, 139 position:pre 140 }); 141 p.css("position", "static"); 142 } 143 p = p.parent(); 144 } 145 self._savedParents = _savedParents; 146 147 //ie6,7 图标到了窗口边界,不可点击,给个padding 148 if (ie < 8) { 149 self.editor.get("toolBarEl").addClass(MAXIMIZE_TOOLBAR_CLASS, undefined); 150 } 151 }, 152 153 /** 154 * 编辑器自身核心状态保存,每次最大化最小化都要save,restore, 155 * firefox修正,iframe layout变化时,range丢了 156 */ 157 _saveEditorStatus:function () { 158 var self = this, 159 editor = self.editor; 160 self.savedRanges = null; 161 if (!UA['gecko'] || !editor.__iframeFocus) { 162 return; 163 } 164 var sel = editor.getSelection(); 165 //firefox 光标丢失bug,位置丢失,所以这里保存下 166 self.savedRanges = sel && sel.getRanges(); 167 }, 168 169 /** 170 * 编辑器自身核心状态恢复,每次最大化最小化都要save,restore, 171 * 维持编辑器核心状态不变 172 */ 173 _restoreEditorStatus:function () { 174 var self = this, 175 editor = self.editor, 176 sel = editor.getSelection(), 177 savedRanges = self.savedRanges; 178 179 //firefox焦点bug 180 181 //原来是聚焦,现在刷新designmode 182 //firefox 先失去焦点才行 183 if (UA['gecko']) { 184 editor.activateGecko(); 185 } 186 187 if (savedRanges && sel) { 188 sel.selectRanges(savedRanges); 189 } 190 191 //firefox 有焦点时才重新聚焦 192 if (editor.__iframeFocus && sel) { 193 var element = sel.getStartElement(); 194 //使用原生不行的,会使主窗口滚动 195 //element[0] && element[0].scrollIntoView(true); 196 element && element.scrollIntoView(undefined, false); 197 } 198 }, 199 200 /** 201 * 将编辑器最大化-实际动作 202 * 必须做两次,何解?? 203 */ 204 _maximize:function (stop) { 205 var self = this, 206 editor = self.editor, 207 editorEl = editor.get("el"), 208 viewportHeight = DOM.viewportHeight(), 209 viewportWidth = DOM.viewportWidth(), 210 textareaEl=editor.get("textarea"), 211 statusHeight = editor.get("statusBarEl") ? 212 editor.get("statusBarEl")[0].offsetHeight : 0, 213 toolHeight = editor.get("toolBarEl")[0].offsetHeight; 214 215 if (!ie) { 216 DOM.css(doc.body, { 217 width:0, 218 height:0, 219 overflow:"hidden" 220 }); 221 } else { 222 doc.body.style.overflow = "hidden"; 223 } 224 doc.documentElement.style.overflow = "hidden"; 225 226 editorEl.css({ 227 position:"absolute", 228 zIndex:Editor.baseZIndex(Editor.zIndexManager.MAXIMIZE), 229 width:viewportWidth + "px" 230 }); 231 iframe.css({ 232 zIndex:Editor.baseZIndex(Editor.zIndexManager.MAXIMIZE - 5), 233 height:viewportHeight + "px", 234 width:viewportWidth + "px" 235 }); 236 editorEl.offset({ 237 left:0, 238 top:0 239 }); 240 iframe.css({ 241 left:0, 242 top:0 243 }); 244 245 textareaEl.parent().css({ 246 height:(viewportHeight - statusHeight - toolHeight ) + "px" 247 }); 248 249 250 textareaEl.css({ 251 height:(viewportHeight - statusHeight - toolHeight ) + "px" 252 }); 253 254 if (stop !== true) { 255 arguments.callee.call(self, true); 256 } 257 }, 258 _real:function () { 259 var self = this, 260 editor = self.editor; 261 if (self._resize) { 262 return; 263 } 264 265 self._saveEditorStatus(); 266 self._saveSate(); 267 self._maximize(); 268 if (!self._resize) { 269 self._resize = S.buffer(function () { 270 self._maximize(); 271 editor.fire("afterMaximizeWindow"); 272 }, 100); 273 } 274 275 Event.on(window, "resize", self._resize); 276 277 setTimeout(function () { 278 self._restoreEditorStatus(); 279 editor.notifySelectionChange(); 280 editor.fire("afterMaximizeWindow"); 281 }, 30); 282 }, 283 maximizeWindow:function () { 284 var self = this, 285 editor = self.editor; 286 if (editor.fire("beforeMaximizeWindow") === false) { 287 return; 288 } 289 init(); 290 self._real(); 291 }, 292 destroy:function () { 293 var self = this; 294 if (self._resize) { 295 Event.remove(window, "resize", self._resize); 296 self._resize = 0; 297 } 298 } 299 }); 300 301 return { 302 init:function (editor) { 303 304 if (!editor.hasCommand("maximizeWindow")) { 305 306 var maximizeCmd = new MaximizeCmd(editor); 307 308 editor.addCommand("maximizeWindow", { 309 exec:function () { 310 maximizeCmd.maximizeWindow(); 311 } 312 }); 313 314 editor.addCommand("restoreWindow", { 315 exec:function () { 316 maximizeCmd.restoreWindow(); 317 } 318 }); 319 320 } 321 322 } 323 }; 324 }, { 325 requires:['editor'] 326 });