[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 /* 2 YUI 3.17.2 (build 9c3c78e) 3 Copyright 2014 Yahoo! Inc. All rights reserved. 4 Licensed under the BSD License. 5 http://yuilibrary.com/license/ 6 */ 7 8 YUI.add('editor-para', function (Y, NAME) { 9 10 11 /** 12 * Plugin for Editor to paragraph auto wrapping and correction. 13 * @class Plugin.EditorPara 14 * @extends Plugin.EditorParaBase 15 * @constructor 16 * @module editor 17 * @submodule editor-para 18 */ 19 20 21 var EditorPara = function() { 22 EditorPara.superclass.constructor.apply(this, arguments); 23 }, HOST = 'host', NODE_CHANGE = 'nodeChange', PARENT_NODE = 'parentNode', 24 FIRST_P = '> p', P = 'p', BR = '<br>', FC = 'firstChild', LI = 'li'; 25 26 27 Y.extend(EditorPara, Y.Plugin.EditorParaBase, { 28 /** 29 * Resolves the ROOT editor element. 30 * @method _getRoot 31 * @private 32 */ 33 _getRoot: function() { 34 return this.get(HOST).getInstance().EditorSelection.ROOT; 35 }, 36 37 /** 38 * nodeChange handler to handle fixing an empty document. 39 * @private 40 * @method _onNodeChange 41 */ 42 _onNodeChange: function(e) { 43 var host = this.get(HOST), inst = host.getInstance(), 44 html, txt, par , d, sel, btag = inst.EditorSelection.DEFAULT_BLOCK_TAG, 45 inHTML, txt2, childs, aNode, node2, top, n, sib, para2, prev, 46 ps, br, item, p, imgs, t, LAST_CHILD = ':last-child', para, b, dir, 47 lc, lc2, found = false, root = this._getRoot(), start; 48 49 switch (e.changedType) { 50 case 'enter-up': 51 para = ((this._lastPara) ? this._lastPara : e.changedNode); 52 b = para.one('br.yui-cursor'); 53 54 if (this._lastPara) { 55 delete this._lastPara; 56 } 57 58 if (b) { 59 if (b.previous() || b.next()) { 60 if (b.ancestor(P)) { 61 b.remove(); 62 } 63 } 64 } 65 if (!para.test(btag)) { 66 para2 = para.ancestor(btag); 67 if (para2) { 68 para = para2; 69 para2 = null; 70 } 71 } 72 if (para.test(btag)) { 73 prev = para.previous(); 74 if (prev) { 75 lc = prev.one(LAST_CHILD); 76 while (!found) { 77 if (lc) { 78 lc2 = lc.one(LAST_CHILD); 79 if (lc2) { 80 lc = lc2; 81 } else { 82 found = true; 83 } 84 } else { 85 found = true; 86 } 87 } 88 if (lc) { 89 host.copyStyles(lc, para); 90 } 91 } 92 } 93 break; 94 case 'enter': 95 if (Y.UA.webkit) { 96 //Webkit doesn't support shift+enter as a BR, this fixes that. 97 if (e.changedEvent.shiftKey) { 98 host.execCommand('insertbr'); 99 e.changedEvent.preventDefault(); 100 } 101 } 102 if (e.changedNode.test('li') && !Y.UA.ie) { 103 html = inst.EditorSelection.getText(e.changedNode); 104 if (html === '') { 105 par = e.changedNode.ancestor('ol,ul'); 106 dir = par.getAttribute('dir'); 107 if (dir !== '') { 108 dir = ' dir = "' + dir + '"'; 109 } 110 par = e.changedNode.ancestor(inst.EditorSelection.BLOCKS); 111 d = inst.Node.create('<p' + dir + '>' + inst.EditorSelection.CURSOR + '</p>'); 112 par.insert(d, 'after'); 113 e.changedNode.remove(); 114 e.changedEvent.halt(); 115 116 sel = new inst.EditorSelection(); 117 sel.selectNode(d, true, false); 118 } 119 } 120 //TODO Move this to a GECKO MODULE - Can't for the moment, requires no change to metadata (YMAIL) 121 if (Y.UA.gecko && host.get('defaultblock') !== 'p') { 122 par = e.changedNode; 123 124 if (!par.test(LI) && !par.ancestor(LI)) { 125 if (!par.test(btag)) { 126 par = par.ancestor(btag); 127 } 128 d = inst.Node.create('<' + btag + '></' + btag + '>'); 129 par.insert(d, 'after'); 130 sel = new inst.EditorSelection(); 131 if (sel.anchorOffset) { 132 inHTML = sel.anchorNode.get('textContent'); 133 134 txt = inst.one(inst.config.doc.createTextNode(inHTML.substr(0, sel.anchorOffset))); 135 txt2 = inst.one(inst.config.doc.createTextNode(inHTML.substr(sel.anchorOffset))); 136 137 aNode = sel.anchorNode; 138 aNode.setContent(''); //I 139 node2 = aNode.cloneNode(); //I 140 node2.append(txt2); //text 141 top = false; 142 sib = aNode; //I 143 while (!top) { 144 sib = sib.get(PARENT_NODE); //B 145 if (sib && !sib.test(btag)) { 146 n = sib.cloneNode(); 147 n.set('innerHTML', ''); 148 n.append(node2); 149 150 //Get children.. 151 childs = sib.get('childNodes'); 152 start = false; 153 /*jshint loopfunc: true */ 154 childs.each(function(c) { 155 if (start) { 156 n.append(c); 157 } 158 if (c === aNode) { 159 start = true; 160 } 161 }); 162 163 aNode = sib; //Top sibling 164 node2 = n; 165 } else { 166 top = true; 167 } 168 } 169 txt2 = node2; 170 sel.anchorNode.append(txt); 171 172 if (txt2) { 173 d.append(txt2); 174 } 175 } 176 if (d.get(FC)) { 177 d = d.get(FC); 178 } 179 d.prepend(inst.EditorSelection.CURSOR); 180 sel.focusCursor(true, true); 181 html = inst.EditorSelection.getText(d); 182 if (html !== '') { 183 inst.EditorSelection.cleanCursor(); 184 } 185 e.changedEvent.preventDefault(); 186 } 187 } 188 break; 189 case 'keyup': 190 if (Y.UA.gecko) { 191 if (root && root.getHTML().length < 20) { 192 if (!root.one(FIRST_P)) { 193 this._fixFirstPara(); 194 } 195 } 196 } 197 break; 198 case 'backspace-up': 199 case 'backspace-down': 200 case 'delete-up': 201 if (!Y.UA.ie) { 202 ps = root.all(FIRST_P); 203 item = root; 204 if (ps.item(0)) { 205 item = ps.item(0); 206 } 207 br = item.one('br'); 208 if (br) { 209 br.removeAttribute('id'); 210 br.removeAttribute('class'); 211 } 212 213 txt = inst.EditorSelection.getText(item); 214 txt = txt.replace(/ /g, '').replace(/\n/g, ''); 215 imgs = item.all('img'); 216 217 if (txt.length === 0 && !imgs.size()) { 218 //God this is horrible.. 219 if (!item.test(P)) { 220 this._fixFirstPara(); 221 } 222 p = null; 223 if (e.changedNode && e.changedNode.test(P)) { 224 p = e.changedNode; 225 } 226 if (!p && host._lastPara && host._lastPara.inDoc()) { 227 p = host._lastPara; 228 } 229 if (p && !p.test(P)) { 230 p = p.ancestor(P); 231 } 232 if (p) { 233 if (!p.previous() && p.get(PARENT_NODE) && p.get(PARENT_NODE).compareTo(root)) { 234 e.changedEvent.frameEvent.halt(); 235 e.preventDefault(); 236 } 237 } 238 } 239 if (Y.UA.webkit) { 240 if (e.changedNode) { 241 //All backspace calls in Webkit need a preventDefault to 242 //stop history navigation #2531299 243 e.preventDefault(); 244 item = e.changedNode; 245 if (item.test('li') && (!item.previous() && !item.next())) { 246 html = item.get('innerHTML').replace(BR, ''); 247 if (html === '') { 248 if (item.get(PARENT_NODE)) { 249 item.get(PARENT_NODE).replace(inst.Node.create(BR)); 250 e.changedEvent.frameEvent.halt(); 251 inst.EditorSelection.filterBlocks(); 252 } 253 } 254 } 255 } 256 } 257 } 258 259 if (Y.UA.gecko) { 260 /* 261 * This forced FF to redraw the content on backspace. 262 * On some occasions FF will leave a cursor residue after content has been deleted. 263 * Dropping in the empty textnode and then removing it causes FF to redraw and 264 * remove the "ghost cursors" 265 */ 266 // d = e.changedNode; 267 // t = inst.config.doc.createTextNode(' '); 268 // d.appendChild(t); 269 // d.removeChild(t); 270 271 this._fixGeckoOnBackspace(inst); 272 } 273 break; 274 } 275 if (Y.UA.gecko) { 276 if (e.changedNode && !e.changedNode.test(btag)) { 277 p = e.changedNode.ancestor(btag); 278 if (p) { 279 this._lastPara = p; 280 } 281 } 282 } 283 284 }, 285 286 //If we just backspaced into a P on FF, we have to put the cursor 287 //before the BR that FF (usually) had injected when we used <ENTER> to 288 //leave the P. 289 _fixGeckoOnBackspace: function (inst) { 290 var sel = new inst.EditorSelection(), 291 node, 292 childNodes; 293 294 //not a cursor, not in a paragraph, or anchored at paragraph start. 295 if (!sel.isCollapsed || sel.anchorNode.get('nodeName') !== 'P' || 296 sel.anchorOffset === 0) { 297 return; 298 } 299 300 //cursor not on the injected final BR 301 childNodes = sel.anchorNode.get('childNodes'); 302 node = sel.anchorNode.get('lastChild'); 303 if (sel.anchorOffset !== childNodes.size() || node.get('nodeName') !== 'BR') { 304 return; 305 } 306 307 //empty P (only contains BR) 308 if (sel.anchorOffset === 1) { 309 sel.selectNode(sel.anchorNode, true); 310 return; 311 } 312 313 //We only expect injected BR behavior when last Node is text 314 node = node.get('previousSibling'); 315 if (node.get('nodeType') !== Node.TEXT_NODE) { 316 return; 317 } 318 319 offset = node.get('length'); 320 321 // the cursor's position is strictly 322 // at the offset when this bug occurs 323 if (sel.getEditorOffset() === offset) { 324 sel.selectNode(node, true, offset); 325 } 326 }, 327 328 initializer: function() { 329 var host = this.get(HOST); 330 if (host.editorBR) { 331 Y.error('Can not plug EditorPara and EditorBR at the same time.'); 332 return; 333 } 334 335 host.on(NODE_CHANGE, Y.bind(this._onNodeChange, this)); 336 } 337 }, { 338 /** 339 * editorPara 340 * @static 341 * @property NAME 342 */ 343 NAME: 'editorPara', 344 /** 345 * editorPara 346 * @static 347 * @property NS 348 */ 349 NS: 'editorPara', 350 ATTRS: { 351 host: { 352 value: false 353 } 354 } 355 }); 356 357 Y.namespace('Plugin'); 358 359 Y.Plugin.EditorPara = EditorPara; 360 361 362 }, '3.17.2', {"requires": ["editor-para-base"]});
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |