JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.1
[ckeditor.git] / _source / plugins / wysiwygarea / plugin.js
index d3b9e62..c2a8b15 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.\r
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.\r
 For licensing, see LICENSE.html or http://ckeditor.com/license\r
 */\r
 \r
@@ -10,18 +10,18 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
 \r
 (function()\r
 {\r
-       /**\r
-        * List of elements in which has no way to move editing focus outside.\r
-        */\r
+       // List of elements in which has no way to move editing focus outside.\r
        var nonExitableElementNames = { table:1,pre:1 };\r
+\r
        // Matching an empty paragraph at the end of document.\r
-       var emptyParagraphRegexp = /\s*<(p|div|address|h\d|center)[^>]*>\s*(?:<br[^>]*>|&nbsp;|\u00A0|&#160;)?\s*(:?<\/\1>)?\s*$/gi;\r
+       var emptyParagraphRegexp = /\s*<(p|div|address|h\d|center)[^>]*>\s*(?:<br[^>]*>|&nbsp;|\u00A0|&#160;)?\s*(:?<\/\1>)?\s*(?=$|<\/body>)/gi;\r
 \r
        function onInsertHtml( evt )\r
        {\r
                if ( this.mode == 'wysiwyg' )\r
                {\r
                        this.focus();\r
+                       this.fire( 'saveSnapshot' );\r
 \r
                        var selection = this.getSelection(),\r
                                data = evt.data;\r
@@ -46,6 +46,11 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                        }\r
                        else\r
                                this.document.$.execCommand( 'inserthtml', false, data );\r
+\r
+                       CKEDITOR.tools.setTimeout( function()\r
+                               {\r
+                                       this.fire( 'saveSnapshot' );\r
+                               }, 0, this );\r
                }\r
        }\r
 \r
@@ -250,7 +255,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                        var isCustomDomain = CKEDITOR.env.isCustomDomain();\r
 \r
                                        // Creates the iframe that holds the editable document.\r
-                                       var createIFrame = function()\r
+                                       var createIFrame = function( data )\r
                                        {\r
                                                if ( iframe )\r
                                                        iframe.remove();\r
@@ -258,46 +263,41 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                                        fieldset.remove();\r
 \r
                                                frameLoaded = 0;\r
-                                               // The document domain must be set within the src\r
-                                               // attribute;\r
-                                               // Defer the script execution until iframe\r
-                                               // has been added to main window, this is needed for some\r
-                                               // browsers which will begin to load the frame content\r
-                                               // prior to it's presentation in DOM.(#3894)\r
-                                               var src = 'void( '\r
-                                                               + ( CKEDITOR.env.gecko ? 'setTimeout' : '' ) + '( function(){' +\r
-                                                               'document.open();' +\r
-                                                               ( CKEDITOR.env.ie && isCustomDomain ? 'document.domain="' + document.domain + '";' : '' ) +\r
-                                                               'document.write( window.parent[ "_cke_htmlToLoad_' + editor.name + '" ] );' +\r
-                                                               'document.close();' +\r
-                                                               'window.parent[ "_cke_htmlToLoad_' + editor.name + '" ] = null;' +\r
-                                                               '}'\r
-                                                               + ( CKEDITOR.env.gecko ? ', 0 )' : ')()' )\r
-                                                               + ' )';\r
-\r
-                                               // Loading via src attribute does not work in Opera.\r
-                                               if ( CKEDITOR.env.opera )\r
-                                                       src = 'void(0);';\r
 \r
                                                iframe = CKEDITOR.dom.element.createFromHtml( '<iframe' +\r
-                                                               ' style="width:100%;height:100%"' +\r
-                                                               ' frameBorder="0"' +\r
-                                                               ' tabIndex="-1"' +\r
-                                                               ' allowTransparency="true"' +\r
-                                                               ' src="javascript:' + encodeURIComponent( src ) + '"' +\r
-                                                               '></iframe>' );\r
+                                                       ' style="width:100%;height:100%"' +\r
+                                                       ' frameBorder="0"' +\r
+                                                       // Support for custom document.domain in IE.\r
+                                                       ( isCustomDomain ?\r
+                                                               ' src="javascript:void((function(){' +\r
+                                                                       'document.open();' +\r
+                                                                       'document.domain=\'' + document.domain + '\';' +\r
+                                                                       'document.close();' +\r
+                                                               '})())"' : '' ) +\r
+                                                       ' tabIndex="-1"' +\r
+                                                       ' allowTransparency="true"' +\r
+                                                       '></iframe>' );\r
+\r
+                                               // Register onLoad event for iframe element, which\r
+                                               // will fill it with content and set custom domain.\r
+                                               iframe.on( 'load', function( e )\r
+                                               {\r
+                                                       e.removeListener();\r
+                                                       var doc = iframe.getFrameDocument().$;\r
+\r
+                                                       // Custom domain handling is needed after each document.open().\r
+                                                       doc.open();\r
+                                                       if ( isCustomDomain )\r
+                                                               doc.domain = document.domain;\r
+                                                       doc.write( data );\r
+                                                       doc.close();\r
+\r
+                                               } );\r
 \r
                                                var accTitle = editor.lang.editorTitle.replace( '%1', editor.name );\r
 \r
                                                if ( CKEDITOR.env.gecko )\r
                                                {\r
-                                                       // Double checking the iframe will be loaded properly(#4058).\r
-                                                       iframe.on( 'load', function( ev )\r
-                                                       {\r
-                                                               ev.removeListener();\r
-                                                               contentDomReady( iframe.$.contentWindow );\r
-                                                       } );\r
-\r
                                                        // Accessibility attributes for Firefox.\r
                                                        mainElement.setAttributes(\r
                                                                {\r
@@ -586,54 +586,107 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
                                                        {\r
                                                                isLoadingData = true;\r
 \r
-                                                               // Get the HTML version of the data.\r
-                                                               if ( editor.dataProcessor )\r
+                                                               var config = editor.config,\r
+                                                                       fullPage = config.fullPage,\r
+                                                                       docType = config.docType;\r
+\r
+                                                               // Build the additional stuff to be included into <head>.\r
+                                                               var headExtra =\r
+                                                                       '<style type="text/css" cke_temp="1">' +\r
+                                                                               editor._.styles.join( '\n' ) +\r
+                                                                       '</style>';\r
+\r
+                                                               !fullPage && ( headExtra =\r
+                                                                       CKEDITOR.tools.buildStyleHtml( editor.config.contentsCss ) +\r
+                                                                       headExtra );\r
+\r
+                                                               var baseTag = config.baseHref ? '<base href="' + config.baseHref + '" cke_temp="1" />' : '';\r
+\r
+                                                               if ( fullPage )\r
                                                                {\r
-                                                                       data = editor.dataProcessor.toHtml( data, fixForBody );\r
+                                                                       // Search and sweep out the doctype declaration.\r
+                                                                       data = data.replace( /<!DOCTYPE[^>]*>/i, function( match )\r
+                                                                               {\r
+                                                                                       editor.docType = docType = match;\r
+                                                                                       return '';\r
+                                                                               });\r
                                                                }\r
 \r
-                                                               data =\r
-                                                                       editor.config.docType +\r
-                                                                       '<html dir="' + editor.config.contentsLangDirection + '">' +\r
-                                                                       '<head>' +\r
-                                                                               '<link type="text/css" rel="stylesheet" href="' +\r
-                                                                               [].concat( editor.config.contentsCss ).join( '"><link type="text/css" rel="stylesheet" href="' ) +\r
-                                                                               '">' +\r
-                                                                               '<style type="text/css" _fcktemp="true">' +\r
-                                                                                       editor._.styles.join( '\n' ) +\r
-                                                                               '</style>'+\r
-                                                                       '</head>' +\r
-                                                                       '<body>' +\r
-                                                                               data +\r
-                                                                       '</body>' +\r
-                                                                       '</html>' +\r
-                                                                       activationScript;\r
-\r
-                                                               window[ '_cke_htmlToLoad_' + editor.name ] = data;\r
-                                                               CKEDITOR._[ 'contentDomReady' + editor.name ] = contentDomReady;\r
-                                                               createIFrame();\r
+                                                               // Get the HTML version of the data.\r
+                                                               if ( editor.dataProcessor )\r
+                                                                       data = editor.dataProcessor.toHtml( data, fixForBody );\r
 \r
-                                                               // Opera must use the old method for loading contents.\r
-                                                               if ( CKEDITOR.env.opera )\r
+                                                               if ( fullPage )\r
                                                                {\r
-                                                                       var doc = iframe.$.contentWindow.document;\r
-                                                                       doc.open();\r
-                                                                       doc.write( data );\r
-                                                                       doc.close();\r
+                                                                       // Check if the <body> tag is available.\r
+                                                                       if ( !(/<body[\s|>]/).test( data ) )\r
+                                                                               data = '<body>' + data;\r
+\r
+                                                                       // Check if the <html> tag is available.\r
+                                                                       if ( !(/<html[\s|>]/).test( data ) )\r
+                                                                               data = '<html>' + data + '</html>';\r
+\r
+                                                                       // Check if the <head> tag is available.\r
+                                                                       if ( !(/<head[\s|>]/).test( data ) )\r
+                                                                               data = data.replace( /<html[^>]*>/, '$&<head><title></title></head>' ) ;\r
+\r
+                                                                       // The base must be the first tag in the HEAD, e.g. to get relative\r
+                                                                       // links on styles.\r
+                                                                       baseTag && ( data = data.replace( /<head>/, '$&' + baseTag ) );\r
+\r
+                                                                       // Inject the extra stuff into <head>.\r
+                                                                       // Attention: do not change it before testing it well. (V2)\r
+                                                                       // This is tricky... if the head ends with <meta ... content type>,\r
+                                                                       // Firefox will break. But, it works if we place our extra stuff as\r
+                                                                       // the last elements in the HEAD.\r
+                                                                       data = data.replace( /<\/head\s*>/, headExtra + '$&' );\r
+\r
+                                                                       // Add the DOCTYPE back to it.\r
+                                                                       data = docType + data;\r
                                                                }\r
+                                                               else\r
+                                                               {\r
+                                                                       data =\r
+                                                                               config.docType +\r
+                                                                               '<html dir="' + config.contentsLangDirection + '">' +\r
+                                                                               '<head>' +\r
+                                                                                       baseTag +\r
+                                                                                       headExtra +\r
+                                                                               '</head>' +\r
+                                                                               '<body' + ( config.bodyId ? ' id="' + config.bodyId + '"' : '' ) +\r
+                                                                                                 ( config.bodyClass ? ' class="' + config.bodyClass + '"' : '' ) +\r
+                                                                                                 '>' +\r
+                                                                                       data +\r
+                                                                               '</html>';\r
+                                                               }\r
+\r
+                                                               data += activationScript;\r
+\r
+                                                               CKEDITOR._[ 'contentDomReady' + editor.name ] = contentDomReady;\r
+                                                               createIFrame( data );\r
                                                        },\r
 \r
                                                        getData : function()\r
                                                        {\r
-                                                               var data = iframe.getFrameDocument().getBody().getHtml();\r
+                                                               var config = editor.config,\r
+                                                                       fullPage = config.fullPage,\r
+                                                                       docType = fullPage && editor.docType,\r
+                                                                       doc = iframe.getFrameDocument();\r
+\r
+                                                               var data = fullPage\r
+                                                                       ? doc.getDocumentElement().getOuterHtml()\r
+                                                                       : doc.getBody().getHtml();\r
 \r
                                                                if ( editor.dataProcessor )\r
                                                                        data = editor.dataProcessor.toDataFormat( data, fixForBody );\r
 \r
                                                                // Strip the last blank paragraph within document.\r
-                                                               if ( editor.config.ignoreEmptyParagraph )\r
+                                                               if ( config.ignoreEmptyParagraph )\r
                                                                        data = data.replace( emptyParagraphRegexp, '' );\r
 \r
+                                                               if ( docType )\r
+                                                                       data = docType + '\n' + data;\r
+\r
                                                                return data;\r
                                                        },\r
 \r