Changeset 969
- Timestamp:
- 02/07/08 07:10:47 (4 years ago)
- Location:
- trunk
- Files:
-
- 1 removed
- 3 modified
- 1 copied
-
XinhaCore.js (modified) (5 diffs)
-
modules/Gecko/paraHandlerBest.js (deleted)
-
modules/Opera (copied) (copied from trunk/modules/Gecko)
-
modules/Opera/Gecko.js (modified) (16 diffs)
-
popups/blank.html (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/XinhaCore.js
r966 r969 134 134 @type string 135 135 */ 136 Xinha.opera_version = navigator.appVersion.substring(0, navigator.appVersion.indexOf(" "))*1; 136 if(Xinha.is_opera && Xinha.agt.match(/opera[\/ ]([0-9.]+)/)) 137 { 138 Xinha.opera_version = parseFloat(RegExp.$1); 139 } 140 else 141 { 142 Xinha.opera_version = 0; 143 } 137 144 /** Browserengine is KHTML (Konqueror, Safari) 138 145 @type string … … 161 168 */ 162 169 Xinha.is_win_ie = (Xinha.is_ie && !Xinha.is_mac); 163 /** Browserengine is Gecko (Mozilla), applies also to Safari 170 /** Browser engine is Gecko (Mozilla), applies also to Safari and Opera which work 171 * largely similar. 164 172 @type string 165 173 */ 166 Xinha.is_gecko = (navigator.product == "Gecko") ;174 Xinha.is_gecko = (navigator.product == "Gecko") || Xinha.is_opera; 167 175 Xinha.is_real_gecko = (navigator.product == "Gecko" && !Xinha.is_webkit); 168 176 Xinha.is_ff3 = Xinha.is_real_gecko && parseInt(navigator.productSub) >= 2007121016; … … 186 194 Xinha.checkSupportedBrowser = function() 187 195 { 188 if ( Xinha.is_opera ) 189 { 190 // alert("Sorry, Opera is not yet supported by Xinha."); 191 return false; 192 } 193 return Xinha.is_real_gecko || (Xinha.is_opera && 0 && Xinha.opera_version >= 9.1) || Xinha.ie_version >= 5.5 || Xinha.webkit_version >= 522; 196 return Xinha.is_real_gecko || (Xinha.is_opera && Xinha.opera_version >= 9.2) || Xinha.ie_version >= 5.5 || Xinha.webkit_version >= 522; 194 197 }; 195 198 /** Cache result of checking for browser support … … 2057 2060 editor._browserSpecificPlugin = editor.registerPlugin('WebKit'); 2058 2061 } 2062 else if (Xinha.is_opera) 2063 { 2064 url = _editor_url + 'modules/Opera/Opera.js'; 2065 if ( !Xinha.loadPlugins(["Opera"], function() { editor.generate(); }, url ) ) 2066 { 2067 return false; 2068 } 2069 editor._browserSpecificPlugin = editor.registerPlugin('Opera'); 2070 } 2059 2071 else if (Xinha.is_gecko) 2060 2072 { … … 2341 2353 editor._iframeLoadDone = false; 2342 2354 if (Xinha.is_opera) 2343 { 2344 Xinha._addEvent( 2345 this._iframe.contentWindow, 2346 'load', 2347 function(e) 2348 { 2349 if ( !editor._iframeLoadDone ) 2350 { 2351 editor._iframeLoadDone = true; 2352 editor.initIframe(); 2353 } 2354 return true; 2355 } 2356 ) 2355 { 2356 editor.initIframe(); 2357 2357 } 2358 2358 else -
trunk/modules/Opera/Gecko.js
r963 r969 11 11 -- This copyright notice MUST stay intact for use. 12 12 -- 13 -- This is the Geckocompatability plugin, part of the Xinha core.13 -- This is the Opera compatability plugin, part of the Xinha core. 14 14 -- 15 15 -- The file is loaded as a special plugin by the Xinha Core when 16 -- Xinha is being run under a Geckobased browser with the Midas16 -- Xinha is being run under an Opera based browser with the Midas 17 17 -- editing API. 18 18 -- … … 22 22 -- Design Notes:: 23 23 -- Most methods here will simply be overriding Xinha.prototype.<method> 24 -- and should be called that, but methods specific to Geckoshould25 -- be a part of the Gecko.prototype, we won't trample on namespace24 -- and should be called that, but methods specific to Opera should 25 -- be a part of the Opera.prototype, we won't trample on namespace 26 26 -- that way. 27 27 -- … … 32 32 --------------------------------------------------------------------------*/ 33 33 34 Gecko._pluginInfo = {35 name : " Gecko",34 Opera._pluginInfo = { 35 name : "Opera", 36 36 origin : "Xinha Core", 37 37 version : "$LastChangedRevision$".replace(/^[^:]*: (.*) \$$/, '$1'), 38 38 developer : "The Xinha Core Developer Team", 39 39 developer_url : "$HeadURL$".replace(/^[^:]*: (.*) \$$/, '$1'), 40 sponsor : " ",41 sponsor_url : " ",40 sponsor : "Gogo Internet Services Limited", 41 sponsor_url : "http://www.gogo.co.nz/", 42 42 license : "htmlArea" 43 43 }; 44 44 45 function Gecko(editor) {45 function Opera(editor) { 46 46 this.editor = editor; 47 editor. Gecko= this;48 } 49 50 /** Allow Geckoto handle some key events in a special way.51 */ 52 53 Gecko.prototype.onKeyPress = function(ev)47 editor.Opera = this; 48 } 49 50 /** Allow Opera to handle some key events in a special way. 51 */ 52 53 Opera.prototype.onKeyPress = function(ev) 54 54 { 55 55 var editor = this.editor; … … 285 285 } 286 286 287 /** When backspace is hit, the GeckoonKeyPress will execute this method.287 /** When backspace is hit, the Opera onKeyPress will execute this method. 288 288 * I don't remember what the exact purpose of this is though :-( 289 289 */ 290 290 291 Gecko.prototype.handleBackspace = function()291 Opera.prototype.handleBackspace = function() 292 292 { 293 293 var editor = this.editor; … … 326 326 }; 327 327 328 Gecko.prototype.inwardHtml = function(html) 329 { 330 // Midas uses b and i internally instead of strong and em 331 // Xinha will use strong and em externally (see Xinha.prototype.outwardHtml) 332 html = html.replace(/<(\/?)strong(\s|>|\/)/ig, "<$1b$2"); 333 html = html.replace(/<(\/?)em(\s|>|\/)/ig, "<$1i$2"); 334 335 // Both IE and Gecko use strike internally instead of del (#523) 328 Opera.prototype.inwardHtml = function(html) 329 { 330 // Both IE and Opera use strike internally instead of del (#523) 336 331 // Xinha will present del externally (see Xinha.prototype.outwardHtml 337 332 html = html.replace(/<(\/?)del(\s|>|\/)/ig, "<$1strike$2"); … … 340 335 } 341 336 342 Gecko.prototype.outwardHtml = function(html) 343 { 344 // ticket:56, the "greesemonkey" plugin for Firefox adds this junk, 345 // so we strip it out. Original submitter gave a plugin, but that's 346 // a bit much just for this IMHO - james 347 html = html.replace(/<script[\s]*src[\s]*=[\s]*['"]chrome:\/\/.*?["']>[\s]*<\/script>/ig, ''); 337 Opera.prototype.outwardHtml = function(html) 338 { 348 339 349 340 return html; 350 341 } 351 342 352 Gecko.prototype.onExecCommand = function(cmdID, UI, param)343 Opera.prototype.onExecCommand = function(cmdID, UI, param) 353 344 { 354 try355 {356 // useCSS deprecated & replaced by styleWithCSS357 this.editor._doc.execCommand('useCSS', false, true); //switch useCSS off (true=off)358 this.editor._doc.execCommand('styleWithCSS', false, false); //switch styleWithCSS off359 } catch (ex) {}360 345 361 346 switch(cmdID) 362 347 { 363 case 'paste': 348 349 /*case 'paste': 364 350 { 365 351 alert(Xinha._lc("The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.")); 366 352 return true; // Indicate paste is done, stop command being issued to browser by Xinha.prototype.execCommand 367 353 } 368 break; 354 break;*/ 355 369 356 case 'removeformat': 370 357 var editor = this.editor; … … 391 378 return true; 392 379 break; 380 393 381 } 394 382 395 383 return false; 396 384 } 397 Gecko.prototype.onMouseDown = function(ev) 385 386 Opera.prototype.onMouseDown = function(ev) 398 387 { 399 // Gecko doesn't select hr's on single click 400 if (ev.target.tagName.toLowerCase() == "hr") 401 { 402 var sel = this.editor.getSelection(); 403 var range = this.editor.createRange(sel); 404 range.selectNode(ev.target); 405 } 388 406 389 } 407 390 … … 411 394 /*--------------------------------------------------------------------------*/ 412 395 396 397 413 398 /** Insert a node at the current selection point. 414 399 * @param toBeInserted DomNode … … 417 402 Xinha.prototype.insertNodeAtSelection = function(toBeInserted) 418 403 { 419 if ( toBeInserted.ownerDocument != this._doc ) // as of FF3, Gecko is strict regarding the ownerDocument of an element404 if ( toBeInserted.ownerDocument != this._doc ) 420 405 { 421 406 try 422 { 423 toBeInserted = this._doc.adoptNode( toBeInserted ); 424 } catch (e) {} 425 } 426 var sel = this.getSelection(); 407 { 408 toBeInserted = this._doc.adoptNode( toBeInserted ); 409 } catch (e) {} 410 } 411 412 this.focusEditor(); 413 414 var sel = this.getSelection(); 427 415 var range = this.createRange(sel); 428 // remove the current selection 429 sel.removeAllRanges(); 416 430 417 range.deleteContents(); 418 431 419 var node = range.startContainer; 432 420 var pos = range.startOffset; 433 421 var selnode = toBeInserted; 422 423 sel.removeAllRanges(); 434 424 435 425 switch ( node.nodeType ) … … 458 448 } 459 449 break; 450 460 451 case 1: // Node.ELEMENT_NODE 461 452 if ( toBeInserted.nodeType == 11 /* Node.DOCUMENT_FRAGMENT_NODE */ ) … … 654 645 Xinha.prototype.getSelection = function() 655 646 { 656 return this._iframe.contentWindow.getSelection(); 647 var sel = this._iframe.contentWindow.getSelection(); 648 if(sel && sel.focusNode && sel.focusNode.tagName && sel.focusNode.tagName == 'HTML') 649 { // Bad news batman, this selection is wonky 650 var bod = this._doc.getElementsByTagName('body')[0]; 651 var rng = this.createRange(); 652 rng.selectNodeContents(bod); 653 sel.removeAllRanges(); 654 sel.addRange(rng); 655 sel.collapseToEnd(); 656 } 657 return sel; 657 658 }; 658 659 … … 717 718 }; 718 719 719 //Control character for retaining edit location when switching modes 720 Xinha.prototype.cc = String.fromCharCode(8286); 721 720 721 /* Caret position remembering when switch between text and html mode. 722 * Largely this is the same as for Gecko except: 723 * 724 * Opera does not have window.find() so we use instead an element with known 725 * id (<span id="XinhaOperaCaretMarker">MARK</span>) so that we can 726 * do _doc.getElementById() on it. 727 * 728 * Opera for some reason will not set the insert point (flashing caret) 729 * anyway though, in theory, the iframe is focused (in findCC below) and then 730 * the selection (containing the span above) is collapsed, it should show 731 * caret. I don't know why not. Seems to require user to actually 732 * click to get the caret to show (or type anything without it acting wierd)? 733 * Very annoying. 734 * 735 */ 736 722 737 Xinha.prototype.setCC = function ( target ) 723 738 { 724 var cc = this.cc; 739 // Do a two step caret insertion, first a single char, then we'll replace that with the 740 // id'd span. 741 var cc = String.fromCharCode(8286); 742 725 743 try 726 744 { … … 741 759 ta.value = ta.value.replace(new RegExp ('(<script[^>]*>[^'+cc+']*?)('+cc+')([^'+cc+']*?<\/script>)'), "$1$3$2"); 742 760 ta.value = ta.value.replace(new RegExp ('^([^'+cc+']*)('+cc+')([^'+cc+']*<body[^>]*>)(.*?)'), "$1$3$2$4"); 761 762 ta.value = ta.value.replace(cc, '<span id="XinhaOperaCaretMarker">MARK</span>'); 743 763 } 744 764 else 745 765 { 746 766 var sel = this.getSelection(); 747 sel.getRangeAt(0).insertNode( this._doc.createTextNode( cc ) ); 767 768 var mark = this._doc.createElement('span'); 769 mark.id = 'XinhaOperaCaretMarker'; 770 sel.getRangeAt(0).insertNode( mark ); 771 748 772 } 749 773 } catch (e) {} … … 753 777 { 754 778 if ( target == 'textarea' ) 755 { 756 var ta = this._textArea; 757 var pos = ta.value.indexOf( this.cc ); 758 if ( pos == -1 ) return; 759 var end = pos + this.cc.length; 760 var before = ta.value.substring( 0, pos ); 761 var after = ta.value.substring( end, ta.value.length ); 762 ta.value = before ; 763 764 ta.scrollTop = ta.scrollHeight; 765 var scrollPos = ta.scrollTop; 766 767 ta.value += after; 768 ta.setSelectionRange(pos,pos); 769 770 ta.focus(); 771 772 ta.scrollTop = scrollPos; 779 { 780 var ta = this._textArea; 781 var pos = ta.value.search( /(<span\s+id="XinhaOperaCaretMarker"\s*\/?>((\s|(MARK))*<\/span>)?)/ ); 782 if ( pos == -1 ) return; 783 var cc = RegExp.$1; 784 var end = pos + cc.length; 785 var before = ta.value.substring( 0, pos ); 786 var after = ta.value.substring( end, ta.value.length ); 787 ta.value = before ; 788 789 ta.scrollTop = ta.scrollHeight; 790 var scrollPos = ta.scrollTop; 791 792 ta.value += after; 793 ta.setSelectionRange(pos,pos); 794 795 ta.focus(); 796 797 ta.scrollTop = scrollPos; 773 798 774 799 } 775 800 else 776 { 777 try 778 { 779 this._iframe.contentWindow.find( this.cc ); 801 { 802 var marker = this._doc.getElementById('XinhaOperaCaretMarker'); 803 if(marker) 804 { 805 this.focusEditor();// this._iframe.contentWindow.focus(); 806 807 var rng = this.createRange(); 808 rng.selectNode(marker); 809 780 810 var sel = this.getSelection(); 781 sel.getRangeAt(0).deleteContents(); 782 this.scrollToElement(); 783 this._iframe.contentWindow.focus(); 784 } catch (e) {} 785 } 786 }; 811 sel.addRange(rng); 812 sel.collapseToStart(); 813 814 this.scrollToElement(marker); 815 816 marker.parentNode.removeChild(marker); 817 return; 818 } 819 } 820 }; 821 787 822 /*--------------------------------------------------------------------------*/ 788 823 /*------------ EXTEND SOME STANDARD "Xinha.prototype" METHODS --------------*/ 789 824 /*--------------------------------------------------------------------------*/ 790 825 826 /* 791 827 Xinha.prototype._standardToggleBorders = Xinha.prototype._toggleBorders; 792 828 Xinha.prototype._toggleBorders = function() 793 829 { 794 830 var result = this._standardToggleBorders(); 795 831 796 832 // flashing the display forces moz to listen (JB:18-04-2005) - #102 797 833 var tables = this._doc.getElementsByTagName('TABLE'); … … 804 840 return result; 805 841 }; 842 */ 806 843 807 844 /** Return the doctype of a document, if set … … 822 859 return d; 823 860 }; 861 862 Xinha.prototype._standardInitIframe = Xinha.prototype.initIframe; 863 Xinha.prototype.initIframe = function() 864 { 865 if(!this._iframeLoadDone) 866 { 867 if(this._iframe.contentWindow && this._iframe.contentWindow.xinhaReadyToRoll) 868 { 869 this._iframeLoadDone = true; 870 this._standardInitIframe(); 871 } 872 else 873 { 874 // Timeout a little (Opera is a bit dodgy about using an event) 875 var editor = this; 876 setTimeout( function() { editor.initIframe() }, 5); 877 } 878 } 879 } 880 881 // For some reason, Opera doesn't listen to addEventListener for at least select elements with event = change 882 // so we will have to intercept those and use a Dom0 event, these are used eg for the fontname/size/format 883 // dropdowns in the toolbar 884 Xinha._addEventOperaOrig = Xinha._addEvent; 885 Xinha._addEvent = function(el, evname, func) 886 { 887 if(el.tagName && el.tagName.toLowerCase() == 'select' && evname == 'change') 888 { 889 return Xinha.addDom0Event(el,evname,func); 890 } 891 892 return Xinha._addEventOperaOrig(el,evname,func); 893 } -
trunk/popups/blank.html
r20 r969 1 <html> 2 </html> 1 <html><body onload="window.xinhaReadyToRoll = true;"></body></html>
