Ticket #4228: shared_spaces_iframe.patch

File shared_spaces_iframe.patch, 20.7 KB (added by Frederico Caldeira Knabben, 10 years ago)

Initial patch for the frames support.

  • _source/themes/default/theme.js

     
    88        function checkSharedSpace( editor, spaceName )
    99        {
    1010                var container,
    11                         element;
     11                        sharedConfig = editor.config.sharedSpaces;
    1212
    13                 // Try to retrieve the target element from the sharedSpaces settings.
    14                 element = editor.config.sharedSpaces;
    15                 element = element && element[ spaceName ];
    16                 element = element && CKEDITOR.document.getById( element );
    17 
    18                 // If the element is available, we'll then create the container for
    19                 // the space.                   
    20                 if ( element )
    21                 {
    22                         // Creates an HTML structure that reproduces the editor class hierarchy.
    23                         var html =
    24                                 '<span class="cke_shared">' +
    25                                 '<span class="' + editor.skinClass + ' cke_editor_' + editor.name + '">' +
    26                                 '<span class="' + CKEDITOR.env.cssClass + '">' +
    27                                 '<span class="cke_wrapper cke_' + editor.lang.dir + '">' +
    28                                 '<span class="cke_editor">' +
    29                                 '<div class="cke_' + spaceName + '">' +
    30                                 '</div></span></span></span></span></span>';
     13                sharedConfig = sharedConfig && sharedConfig[ spaceName ];
     14               
     15                if ( sharedConfig )
     16                {
     17                        // Retrieve the element id/location from the setting.
     18                        var element = sharedConfig.match( /^(?:(?:(.+?)\((\w+)\))|(.+))$/ );
     19
     20                        // If the group 3 is defined, we have the "elementId" syntax.
     21                        if ( element[ 3 ] )     
     22                                element = CKEDITOR.document.getById( element[ 3 ] );
     23                        // Otherwise we have "windowName(elementId)".
     24                        else                                   
     25                        {
     26                                var targetWindow = window,
     27                                        targetDoc,
     28                                        targetWindowParts = element[ 1 ].split( '.' ) ;
     29
     30                                while ( targetWindowParts.length )
     31                                {
     32                                        var part = targetWindowParts.shift() ;
     33                                        if ( part.length > 0 )
     34                                                targetWindow = targetWindow[ part ] ;
     35                                }
     36                               
     37                                if ( targetWindow )
     38                                {
     39                                        targetDoc = new CKEDITOR.dom.document( targetWindow.document );
     40                                        targetWindow = new CKEDITOR.dom.window( targetWindow );
     41
     42                                        // Get the element in the target.
     43                                        element = targetDoc.getById( element[ 2 ] );
     44                                       
     45                                        if ( element )
     46                                        {
     47                                                // Bridge the CKEDITOR object.
     48                                                targetWindow.$.CKEDITOR = CKEDITOR;
     49
     50                                                if ( !targetWindow.getCustomData( 'cke_getById' ) )
     51                                                {
     52                                                        // Expand element finding scope to include target document.
     53                                                        CKEDITOR.document.getById = CKEDITOR.tools.override( CKEDITOR.document.getById,
     54                                                                function( originalGetById )
     55                                                                {
     56                                                                        return function( id )
     57                                                                        {
     58                                                                                return originalGetById.call( this, id ) || targetDoc.getById( id );
     59                                                                        }
     60                                                                });
     61                                                       
     62                                                        targetWindow.setCustomData( 'cke_getById', 1 );
     63                                                }
     64                                               
     65                                                var skinName = editor.skinName ;
     66                                                if ( !targetWindow.getCustomData( 'cke_skin' + skinName + '_editor' ) )
     67                                                {
     68                                                        // Loads editor skin part into target window.
     69                                                        var part = CKEDITOR.skins[ skinName ].editor;
     70                                                        for ( var c = 0 ; c < part.css.length ; c++ )
     71                                                                targetDoc.appendStyleSheet( part.css[ c ] );
     72                                                       
     73                                                        targetWindow.setCustomData( 'cke_skin' + skinName, 1 );
     74                                                }
     75                                        }
     76                                }
     77                        }
     78
     79                        // If the element is available, we'll then create the container for
     80                        // the space.                   
     81                        if ( element )
     82                        {
     83                                // Creates an HTML structure that reproduces the editor class hierarchy.
     84                                var html =
     85                                        '<span class="cke_shared">' +
     86                                        '<span class="' + editor.skinClass + ' cke_editor_' + editor.name + '">' +
     87                                        '<span class="' + CKEDITOR.env.cssClass + '">' +
     88                                        '<span class="cke_wrapper cke_' + editor.lang.dir + '">' +
     89                                        '<span class="cke_editor">' +
     90                                        '<div class="cke_' + spaceName + '">' +
     91                                        '</div></span></span></span></span></span>';
    3192
    32                         var mainContainer = element.append( CKEDITOR.dom.element.createFromHtml( html, element.getDocument() ) );
     93                                var mainContainer = element.append( CKEDITOR.dom.element.createFromHtml( html, element.getDocument() ) );
    3394
    34                         // Only the first container starts visible. Others get hidden.
    35                         if ( element.getCustomData( 'cke_hasshared' ) )
    36                                 mainContainer.hide();
    37                         else
    38                                 element.setCustomData( 'cke_hasshared', 1 );
    39                        
    40                         // Get the deeper inner <div>.
    41                         container = mainContainer.getChild( [0,0,0,0] );
     95                                // Only the first container starts visible. Others get hidden.
     96                                if ( element.getCustomData( 'cke_hasshared' ) )
     97                                        mainContainer.hide( );
     98                                else
     99                                        element.setCustomData( 'cke_hasshared', 1 );
     100
     101                               
     102                                // Get the deeper inner <div>.
     103                                container = mainContainer.getChild( [0,0,0,0] );
    42104
    43                         // When the editor gets focus, we show the space container, hiding others.
    44                         editor.on( 'focus', function()
    45                                 {
    46                                         for ( var i = 0, sibling, children = element.getChildren() ; ( sibling = children.getItem( i ) ) ; i++ )
    47                                         {
    48                                                 if ( sibling.type == CKEDITOR.NODE_ELEMENT
    49                                                         && !sibling.equals( mainContainer )
    50                                                         && sibling.hasClass( 'cke_shared' ) )
    51                                                 {
    52                                                         sibling.hide();
    53                                                 }
    54                                         }
     105                                // When the editor gets focus, we show the space container, hiding others.
     106                                editor.on( 'focus', function()
     107                                        {
     108                                                for ( var i = 0, sibling, children = element.getChildren() ; ( sibling = children.getItem( i ) ) ; i++ )
     109                                                {
     110                                                        if ( sibling.type == CKEDITOR.NODE_ELEMENT
     111                                                                && !sibling.equals( mainContainer )
     112                                                                && sibling.hasClass( 'cke_shared' ) )
     113                                                        {
     114                                                                sibling.hide();
     115                                                        }
     116                                                }
    55117
    56                                         mainContainer.show();
    57                                 });
     118                                                mainContainer.show();
     119                                        });
    58120
    59                         editor.on( 'destroy', function()
    60                                 {
    61                                         mainContainer.remove();
    62                                 });
    63                 }
     121                                editor.on( 'destroy', function()
     122                                        {
     123                                                mainContainer.remove();
     124                                        });
     125                        }
     126                }
    64127
    65128                return container;
    66129        }
     
    161224
    162225                buildDialog : function( editor )
    163226                {
     227                        var skinName = editor.skinName;
     228
     229                        editor.on( 'dialogReady', function( evt )
     230                        {
     231                                var dialog = evt.data,
     232                                        dialogDoc = dialog._.document,
     233                                        targetWin = dialogDoc.getWindow();
     234
     235                                if( !( targetWin.equals( CKEDITOR.document.getWindow() )
     236                                           || targetWin.getCustomData( 'cke_skin' + skinName + '_dialog') ) )
     237                                {
     238                                        // Loads dialog skin part into dialog living window.
     239                                        var part = CKEDITOR.skins[ skinName ].dialog;
     240                                        for ( var c = 0 ; c < part.css.length ; c++ )
     241                                                dialogDoc.appendStyleSheet( part.css[ c ] );
     242                                }
     243                        } );
     244
    164245                        var baseIdNumber = CKEDITOR.tools.getNextNumber();
    165246
    166247                        var element = CKEDITOR.dom.element.createFromHtml( [
  • _source/plugins/panelbutton/plugin.js

     
    8888                                        return;
    8989
    9090                                var panelDefinition = this._.panelDefinition || {},
    91                                         panelParentElement = panelDefinition.parent || CKEDITOR.document.getBody(),
     91                                        panelParentElement = panelDefinition.parent || this.getElement().getDocument().getBody(),
    9292                                        panel = this._.panel = new CKEDITOR.ui.floatPanel( editor, panelParentElement, panelDefinition ),
    9393                                        me = this;
    9494
     
    133133                                                                _.on = 0;
    134134                                                                me.setState( CKEDITOR.TRISTATE_OFF );
    135135                                                };
     136                        },
     137
     138                        getElement : function()
     139                        {
     140                                return this.document.getById( this._.id );
    136141                        }
    137142                }
    138143        });
  • _source/plugins/dialog/plugin.js

     
    101101                        }
    102102                        , editor ).definition;
    103103
    104                 var doc = CKEDITOR.document;
    105 
    106104                var themeBuilt = editor.theme.buildDialog( editor );
    107105
    108106                // Initialize some basic parameters.
    109107                this._ =
    110108                {
    111109                        editor : editor,
     110                        document : new CKEDITOR.dom.document( top.document ),
    112111                        element : themeBuilt.element,
    113112                        name : dialogName,
    114113                        contentSize : { width : 0, height : 0 },
     
    327326                // Add the dialog keyboard handlers.
    328327                this.on( 'show', function()
    329328                        {
    330                                 CKEDITOR.document.on( 'keydown', focusKeydownHandler, this, null, 0 );
     329                                this._.document.on( 'keydown', focusKeydownHandler, this, null, 0 );
    331330                                // Some browsers instead, don't cancel key events in the keydown, but in the
    332331                                // keypress. So we must do a longer trip in those cases. (#4531)
    333332                                if ( CKEDITOR.env.opera || ( CKEDITOR.env.gecko && CKEDITOR.env.mac ) )
    334                                         CKEDITOR.document.on( 'keypress', focusKeyPressHandler, this );
     333                                        this._.document.on( 'keypress', focusKeyPressHandler, this );
    335334
    336335                                if ( CKEDITOR.env.ie6Compat )
    337336                                {
     
    341340                        } );
    342341                this.on( 'hide', function()
    343342                        {
    344                                 CKEDITOR.document.removeListener( 'keydown', focusKeydownHandler );
     343                                this._.document.removeListener( 'keydown', focusKeydownHandler );
    345344                        } );
    346345                this.on( 'iframeAdded', function( evt )
    347346                        {
     
    398397                initResizeHandles( this );
    399398
    400399                // Insert the title.
    401                 ( new CKEDITOR.dom.text( definition.title, CKEDITOR.document ) ).appendTo( this.parts.title );
     400                ( new CKEDITOR.dom.text( definition.title, this._.document ) ).appendTo( this.parts.title );
    402401
    403402                // Insert the tabs and contents.
    404403                for ( var i = 0 ; i < definition.contents.length ; i++ )
     
    443442                        this._.buttons[ buttons[i].id ] = buttons[i];
    444443
    445444                CKEDITOR.skins.load( editor, 'dialog' );
     445                editor.fire( 'dialogReady', this );
    446446        };
    447447
    448448        // Focusable interface. Use it via dialog.addFocusable.
     
    551551                                // If not fixed positioned, add scroll position to the coordinates.
    552552                                if ( !isFixed )
    553553                                {
    554                                         var scrollPosition = CKEDITOR.document.getWindow().getScrollPosition();
     554                                        var scrollPosition = this._.document.getWindow().getScrollPosition();
    555555                                        x += scrollPosition.x;
    556556                                        y += scrollPosition.y;
    557557                                }
     
    587587                        }
    588588
    589589                        // Insert the dialog's element to the root document.
    590                         var element = this._.element;
     590                        var element = this._.element,
     591                                doc = this._.document,
     592                                dialogParentElement = doc.getBody();
     593
    591594                        var definition = this.definition;
    592                         if ( !( element.getParent() && element.getParent().equals( CKEDITOR.document.getBody() ) ) )
    593                                 element.appendTo( CKEDITOR.document.getBody() );
     595
     596                        if ( !dialogParentElement.equals( element.getParent() ) )
     597                                element.appendTo( dialogParentElement );
    594598                        else
    595599                                return;
    596600
     
    655659                        // Rearrange the dialog to the middle of the window.
    656660                        CKEDITOR.tools.setTimeout( function()
    657661                                {
    658                                         var viewSize = CKEDITOR.document.getWindow().getViewPaneSize();
     662                                        var viewSize = this._.document.getWindow().getViewPaneSize();
    659663                                        var dialogSize = this.getSize();
    660664
    661665                                        // We're using definition size for initial position because of
     
    14511455                function mouseMoveHandler( evt )
    14521456                {
    14531457                        var dialogSize = dialog.getSize(),
    1454                                 viewPaneSize = CKEDITOR.document.getWindow().getViewPaneSize(),
     1458                                viewPaneSize = dialog._.document.getWindow().getViewPaneSize(),
    14551459                                x = evt.data.$.screenX,
    14561460                                y = evt.data.$.screenY,
    14571461                                dx = x - lastCoords.x,
     
    14831487
    14841488                function mouseUpHandler( evt )
    14851489                {
    1486                         CKEDITOR.document.removeListener( 'mousemove', mouseMoveHandler );
    1487                         CKEDITOR.document.removeListener( 'mouseup', mouseUpHandler );
     1490                        this.removeListener( 'mousemove', mouseMoveHandler );
     1491                        this.removeListener( 'mouseup', mouseUpHandler );
    14881492
    14891493                        if ( CKEDITOR.env.ie6Compat )
    14901494                        {
     
    15001504
    15011505                                lastCoords = { x : evt.data.$.screenX, y : evt.data.$.screenY };
    15021506
    1503                                 CKEDITOR.document.on( 'mousemove', mouseMoveHandler );
    1504                                 CKEDITOR.document.on( 'mouseup', mouseUpHandler );
     1507                                this._.document.on( 'mousemove', mouseMoveHandler );
     1508                                this._.document.on( 'mouseup', mouseUpHandler );
    15051509                                abstractDialogCoords = dialog.getPosition();
    15061510
    15071511                                if ( CKEDITOR.env.ie6Compat )
     
    15591563                                } );
    15601564                        lastCoords = { x : evt.data.$.screenX, y : evt.data.$.screenY };
    15611565
    1562                         CKEDITOR.document.on( 'mousemove', mouseMoveHandler, dialog, { part : partName } );
    1563                         CKEDITOR.document.on( 'mouseup', mouseUpHandler, dialog, { part : partName } );
     1566                        this._.document.on( 'mousemove', mouseMoveHandler, dialog, { part : partName } );
     1567                        this._.document.on( 'mouseup', mouseUpHandler, dialog, { part : partName } );
    15641568
    15651569                        if ( CKEDITOR.env.ie6Compat )
    15661570                        {
     
    15781582                                y = evt.data.$.screenY,
    15791583                                dx = x - lastCoords.x,
    15801584                                dy = y - lastCoords.y,
    1581                                 viewPaneSize = CKEDITOR.document.getWindow().getViewPaneSize(),
     1585                                viewPaneSize = this._.document.getWindow().getViewPaneSize(),
    15821586                                partName = evt.listenerData.part;
    15831587
    15841588                        if ( partName.search( 't' ) != -1 )
     
    16301634
    16311635                function mouseUpHandler( evt )
    16321636                {
    1633                         CKEDITOR.document.removeListener( 'mouseup', mouseUpHandler );
    1634                         CKEDITOR.document.removeListener( 'mousemove', mouseMoveHandler );
     1637                        this._.document.removeListener( 'mouseup', mouseUpHandler );
     1638                        this._.document.removeListener( 'mousemove', mouseMoveHandler );
    16351639
    16361640                        if ( CKEDITOR.env.ie6Compat )
    16371641                        {
     
    16601664
    16611665        var resizeCover;
    16621666        var coverElement;
     1667        var win = new CKEDITOR.dom.window( top );
    16631668
    16641669        var addCover = function( editor )
    16651670        {
    1666                 var win = CKEDITOR.document.getWindow();
    1667 
    16681671                if ( !coverElement )
    16691672                {
    16701673                        var backgroundColorStyle = editor.config.dialog_backgroundCoverColor || 'white';
     
    17671770                var opacity = editor.config.dialog_backgroundCoverOpacity;
    17681771                element.setOpacity( typeof opacity != 'undefined' ? opacity : 0.5 );
    17691772
    1770                 element.appendTo( CKEDITOR.document.getBody() );
     1773                element.appendTo( new CKEDITOR.dom.element( win.$.document.body ) );
    17711774        };
    17721775
    17731776        var removeCover = function()
     
    17751778                if ( !coverElement )
    17761779                        return;
    17771780
    1778                 var win = CKEDITOR.document.getWindow();
    17791781                coverElement.remove();
    17801782                win.removeListener( 'resize', resizeCover );
    17811783
     
    21922194                 */
    21932195                getElement : function()
    21942196                {
    2195                         return CKEDITOR.document.getById( this.domId );
     2197                        return this._.dialog._.document.getById( this.domId );
    21962198                },
    21972199
    21982200                /**
     
    27152717                                throw new Error( '[CKEDITOR.dialog.openDialog] Dialog "' + dialogName + '" failed when loading definition.' );
    27162718
    27172719                        // Not loaded? Load the .js file first.
    2718                         var body = CKEDITOR.document.getBody(),
     2720                        var body = new CKEDITOR.dom.element( top.document.body ),
    27192721                                cursor = body.$.style.cursor,
    27202722                                me = this;
    27212723
  • _source/plugins/richcombo/plugin.js

     
    207207                                return;
    208208
    209209                        var panelDefinition = this._.panelDefinition,
    210                                 panelParentElement = panelDefinition.parent || CKEDITOR.document.getBody(),
     210                                panelParentElement = panelDefinition.parent || this.getElement().getDocument().getBody();
    211211                                panel = new CKEDITOR.ui.floatPanel( editor, panelParentElement, panelDefinition ),
    212212                                list = panel.addListBlock( this.id, this.multiSelect ),
    213213                                me = this;
     
    277277                                this.init();
    278278                },
    279279
     280                getElement : function()
     281                {
     282                        return this.document.getById( 'cke_' + this.id );
     283                },
     284               
    280285                setValue : function( value, text )
    281286                {
    282287                        this._.value = value;
  • _source/core/skins.js

     
    2323        var loadPart = function( editor, skinName, part, callback )
    2424        {
    2525                // Get the skin definition.
    26                 var skinDefinition = loaded[ skinName ];
     26                var skinDefinition = CKEDITOR.skins[ skinName ] = loaded[ skinName ];
    2727
    2828                if ( !editor.skin )
    2929                {
  • _samples/sharedspaces_iframe/inner_iframe.html

     
     1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     2<!--
     3Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
     4For licensing, see LICENSE.html or http://ckeditor.com/license
     5-->
     6<html xmlns="http://www.w3.org/1999/xhtml">
     7<head>
     8        <title>Shared Spaces - Inner Page - CKEditor Sample</title>
     9<!-- CKReleaser %REMOVE_LINE%
     10        <script type="text/javascript" src="../../ckeditor.js"></script>
     11CKReleaser %REMOVE_START% -->
     12        <script type="text/javascript" src="../../ckeditor_source.js"></script>
     13<!-- CKReleaser %REMOVE_END% -->
     14</head>
     15<body>
     16        <form id="editorsForm" action="../sample_posteddata.php" method="post">
     17                <p>
     18                        <label for="editor1">
     19                                Editor 1 (uses the shared toolbar and element path):</label><br />
     20                        <textarea id="editor1" name="editor1" rows="10" cols="80">&lt;p&gt;This is some &lt;strong&gt;sample text&lt;/strong&gt;. You are using &lt;a href="http://ckeditor.com/"&gt;CKEditor&lt;/a&gt;.&lt;/p&gt;</textarea>
     21                        <script type="text/javascript">
     22                        //<![CDATA[
     23
     24                                CKEDITOR.replace( 'editor1',
     25                                        {
     26                                                sharedSpaces :
     27                                                {
     28                                                        top : 'parent(topSpace)',
     29                                                        bottom : 'parent(bottomSpace)'
     30                                                },
     31
     32                                                // Removes the maximize plugin as it's not usable
     33                                                // in a shared toolbar.
     34                                                // Removes the resizer as it's not usable in a
     35                                                // shared elements path.
     36                                                removePlugins : 'maximize,resize'
     37                                        } );
     38
     39                        //]]>
     40                        </script>
     41                </p>
     42                <p>
     43                        <label for="editor2">
     44                                Editor 2 (uses the shared toolbar and element path):</label><br />
     45                        <textarea id="editor2" name="editor2" rows="10" cols="80">&lt;p&gt;This is some &lt;strong&gt;sample text&lt;/strong&gt;. You are using &lt;a href="http://ckeditor.com/"&gt;CKEditor&lt;/a&gt;.&lt;/p&gt;</textarea>
     46                        <script type="text/javascript">
     47                        //<![CDATA[
     48                                CKEDITOR.replace( 'editor2',
     49                                        {
     50                                                sharedSpaces :
     51                                                {
     52                                                        top : 'parent(topSpace)',
     53                                                        bottom : 'parent(bottomSpace)'
     54                                                },
     55
     56                                                // Removes the maximize plugin as it's not usable
     57                                                // in a shared toolbar.
     58                                                // Removes the resizer as it's not usable in a
     59                                                // shared elements path.
     60                                                removePlugins : 'maximize,resize'
     61                                        } );
     62
     63                        //]]>
     64                        </script>
     65                </p>
     66                <p>
     67                        <label for="editor3">
     68                                Editor 3 (uses the shared toolbar only):</label><br />
     69                        <textarea id="editor3" name="editor3" rows="10" cols="80">&lt;p&gt;This is some &lt;strong&gt;sample text&lt;/strong&gt;. You are using &lt;a href="http://ckeditor.com/"&gt;CKEditor&lt;/a&gt;.&lt;/p&gt;</textarea>
     70                        <script type="text/javascript">
     71                        //<![CDATA[
     72                                CKEDITOR.replace( 'editor3',
     73                                        {
     74                                                sharedSpaces :
     75                                                {
     76                                                        top : 'parent(topSpace)'
     77                                                },
     78                                               
     79                                                // Removes the maximize plugin as it's not usable
     80                                                // in a shared toolbar.
     81                                                removePlugins : 'maximize'
     82                                        } );
     83
     84                        //]]>
     85                        </script>
     86                </p>
     87                <p>
     88                        <label for="editor4">
     89                                Editor 4 (no shared spaces):</label><br />
     90                        <textarea id="editor4" name="editor4" rows="10" cols="80">&lt;p&gt;This is some &lt;strong&gt;sample text&lt;/strong&gt;. You are using &lt;a href="http://ckeditor.com/"&gt;CKEditor&lt;/a&gt;.&lt;/p&gt;</textarea>
     91                        <script type="text/javascript">
     92                        //<![CDATA[
     93                                CKEDITOR.replace( 'editor4' );
     94
     95                        //]]>
     96                        </script>
     97                </p>
     98                <p>
     99                        <input type="submit" value="Submit" />
     100                </p>
     101        </form>
     102</body>
     103</html>
  • _samples/sharedspaces_iframe.html

     
     1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     2<!--
     3Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
     4For licensing, see LICENSE.html or http://ckeditor.com/license
     5-->
     6<html xmlns="http://www.w3.org/1999/xhtml">
     7<head>
     8        <title>Shared Spaces - CKEditor Sample</title>
     9        <script type="text/javascript" src="sample.js"></script>
     10        <style id="styles" type="text/css">
     11
     12iframe
     13{
     14        height: 400px;
     15        width: 100%;
     16        overflow: auto;
     17        border: solid 1px #555;
     18        margin: 10px 0;
     19}
     20
     21        </style>
     22</head>
     23<body>
     24        <div id="html">
     25                <div id="topSpace">
     26                </div>
     27                <iframe src="sharedspaces_iframe/inner_iframe.html"></iframe>
     28                <div id="bottomSpace">
     29                </div>
     30        </div>
     31        <div id="code">
     32                <pre></pre>
     33        </div>
     34</body>
     35</html>
© 2003 – 2019 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy