Changeset 243

Show
Ignore:
Timestamp:
2007-04-09 00:34:47 (3 years ago)
Author:
mjk
Message:

Added dynamic table sizing, Anchor Delete, additional selection utilities

Location:
FCKeditor/branches/developers/mjk/editor/_source
Files:
11 modified

Legend:

Unmodified
Added
Removed
  • FCKeditor/branches/developers/mjk/editor/_source/classes/fckspecialcombo.js

    r132 r243  
    139139        for ( var i in this.Items ) 
    140140        { 
     141                if ( !this.Items[i] ) continue; 
    141142                this.Items[i].className = this.Items[i].originalClass = 'SC_Item' ; 
    142143                this.Items[i].Selected = false ; 
     
    176177 
    177178        this._OuterTable.className = isEnabled ? '' : 'SC_FieldDisabled' ; 
     179} 
     180 
     181FCKSpecialCombo.prototype.ClearItems = function () 
     182{ 
     183        if ( this.Items ) 
     184        { 
     185                for ( var key in this.Items ) 
     186                        this.Items[key] = null ; 
     187        } 
     188        while (this._ItemsHolderEl.firstChild) 
     189                this._ItemsHolderEl.removeChild(this._ItemsHolderEl.firstChild); 
    178190} 
    179191 
  • FCKeditor/branches/developers/mjk/editor/_source/commandclasses/fck_othercommands.js

    r174 r243  
    9999        if ( typeof( fontSize ) == 'string' ) fontSize = parseInt(fontSize, 10) ; 
    100100 
    101         if ( fontSize == null || fontSize == '' ) 
    102         { 
    103                 // TODO: Remove font size attribute (Now it works with size 3. Will it work forever?) 
    104                 FCK.ExecuteNamedCommand( 'FontSize', 3 ) ; 
     101        // If user wants the font size cleared, we have to find 
     102        // where the font size tag is and go clear it (if there's one) 
     103        if ( !fontSize || fontSize == null || fontSize == '' ) 
     104        { 
     105                var oFont = FCK.Selection.MoveToAncestorNode('FONT'); 
     106                if ( oFont && oFont.getAttribute("size") ) 
     107                { 
     108                        //if the only thing here is SIZE, collapse the whole tag 
     109                        if (oFont.attributes.length == 1 || 
     110                                (oFont.outerHTML && oFont.outerHTML.search(/<FONT size=["]*\d["]*>/i))) 
     111                        { 
     112                                FCKTools.RemoveOuterTags(oFont); 
     113                        } 
     114                        else 
     115                                oFont.removeAttribute("size"); 
     116                }        
    105117        } 
    106118        else 
    107119                FCK.ExecuteNamedCommand( 'FontSize', fontSize ) ; 
    108120} 
     121 
    109122 
    110123FCKFontSizeCommand.prototype.GetState = function() 
     
    380393        } 
    381394} ; 
     395 
     396var FCKAnchorDeleteCommand = function() 
     397{ 
     398        this.Name = 'AnchorDelete' ; 
     399} 
     400 
     401FCKAnchorDeleteCommand.prototype.Execute = function() 
     402{ 
     403        if (FCK.Selection.GetType() == 'Control') 
     404        { 
     405                FCK.Selection.Delete(); 
     406        } 
     407        else 
     408        { 
     409                var oFakeImage = FCK.Selection.GetSelectedElement() ; 
     410                if ( oFakeImage ) 
     411                { 
     412                        if ( oFakeImage.tagName == 'IMG' && oFakeImage.getAttribute('_fckanchor') ) 
     413                                oAnchor = FCK.GetRealElement( oFakeImage ) ; 
     414                        else 
     415                                oFakeImage = null ; 
     416                } 
     417                 
     418                //Search for a real anchor 
     419                if ( !oFakeImage ) 
     420                { 
     421                        oAnchor = FCK.Selection.MoveToAncestorNode( 'A' ) ; 
     422                        if ( oAnchor ) 
     423                                FCK.Selection.SelectNode( oAnchor ) ; 
     424                } 
     425 
     426                // If it's also a link, then just remove the name and exit 
     427                if ( oAnchor.href.length != 0 ) 
     428                { 
     429                        oAnchor.removeAttribute( 'name' ) ; 
     430                        // Remove temporary class for IE 
     431                        if ( FCKBrowserInfo.IsIE ) 
     432                                oAnchor.className = oAnchor.className.replace( FCKRegexLib.FCK_Class, '' ) ; 
     433                        return ; 
     434                } 
     435         
     436                // We need to remove the anchor 
     437                // If we got a fake image, then just remove it and we're done 
     438                if ( oFakeImage ) 
     439                { 
     440                        oFakeImage.parentNode.removeChild( oFakeImage ) ; 
     441                        return ; 
     442                } 
     443                // Empty anchor, so just remove it 
     444                if ( oAnchor.innerHTML.length == 0 ) 
     445                { 
     446                        oAnchor.parentNode.removeChild( oAnchor ) ; 
     447                        return ; 
     448                } 
     449                // Anchor with content, leave the content 
     450                FCKTools.RemoveOuterTags( oAnchor ) ; 
     451        } 
     452        if ( FCKBrowserInfo.IsGecko ) 
     453                FCK.Selection.Collapse( true ) ; 
     454} 
     455 
     456FCKAnchorDeleteCommand.prototype.GetState = function() 
     457{ 
     458        return FCK.GetNamedCommandState( 'Unlink') ; 
     459} 
     460 
  • FCKeditor/branches/developers/mjk/editor/_source/internals/fckcommands.js

    r174 r243  
    4444                case 'Unlink'           : oCommand = new FCKUnlinkCommand() ; break ; 
    4545                case 'Anchor'           : oCommand = new FCKDialogCommand( 'Anchor'             , FCKLang.DlgAnchorTitle                , 'dialog/fck_anchor.html'              , 370, 170 ) ; break ; 
     46                case 'AnchorDelete'     : oCommand = new FCKAnchorDeleteCommand() ; break ; 
    4647                case 'BulletedList'     : oCommand = new FCKDialogCommand( 'BulletedList', FCKLang.BulletedListProp             , 'dialog/fck_listprop.html?UL' , 370, 170 ) ; break ; 
    4748                case 'NumberedList'     : oCommand = new FCKDialogCommand( 'NumberedList', FCKLang.NumberedListProp             , 'dialog/fck_listprop.html?OL' , 370, 170 ) ; break ; 
  • FCKeditor/branches/developers/mjk/editor/_source/internals/fck_contextmenu.js

    r202 r243  
    141141                                        menu.AddSeparator() ; 
    142142                                        menu.AddItem( 'Anchor', FCKLang.AnchorProp, 36 ) ; 
     143                                        menu.AddItem( 'AnchorDelete', FCKLang.AnchorDelete) ; 
    143144                                } 
    144145                        }} ; 
  • FCKeditor/branches/developers/mjk/editor/_source/internals/fck_gecko.js

    r175 r243  
    3939        } 
    4040 
     41        //allow the table handler to handle mouse messages for dynamic table sizing 
     42        this._ExecMouseDown = function(e) 
     43        { 
     44                FCK.Events.FireEvent( "OnMouseDown",e ) ; 
     45        } 
     46 
     47        this._ExecMouseMove = function(e) 
     48        { 
     49                FCK.Events.FireEvent( "OnMouseMove",e ) ; 
     50        } 
     51 
     52        this._ExecMouseUp = function(e) 
     53        { 
     54                FCK.Events.FireEvent( "OnMouseUp",e ) ; 
     55        } 
    4156        this.ExecOnSelectionChangeTimer = function() 
    4257        { 
     
    6378        FCK.ContextMenu._InnerContextMenu.SetMouseClickWindow( FCK.EditorWindow ) ; 
    6479        FCK.ContextMenu._InnerContextMenu.AttachToElement( FCK.EditorDocument ) ; 
     80         
     81        //Hooks for table sizing 
     82        this.EditorDocument.addEventListener( 'mousedown', this._ExecMouseDown, true ) ; 
     83        this.EditorDocument.addEventListener( 'mouseup', this._ExecMouseUp, true ) ; 
     84        this.EditorDocument.addEventListener( 'mousemove', this._ExecMouseMove, true ) ; 
     85 
    6586} 
    6687 
     
    99120        Copy    : true 
    100121} ; 
     122 
    101123 
    102124// ExecuteNamedCommand overload for Gecko. 
  • FCKeditor/branches/developers/mjk/editor/_source/internals/fck_ie.js

    r202 r243  
    7070                FCK.EditorWindow.event.returnValue      = false ; 
    7171        } 
     72        FCK.Events.FireEvent( "OnMouseUp",FCK.EditorWindow.event) ; 
     73} 
     74 
     75function Doc_OnMouseDown() 
     76{ 
     77        FCK.Events.FireEvent( "OnMouseDown",FCK.EditorWindow.event ) ; 
     78} 
     79 
     80function Doc_OnMouseMove() 
     81{ 
     82        FCK.Events.FireEvent( "OnMouseMove",FCK.EditorWindow.event) ; 
    7283} 
    7384 
     
    140151 
    141152        this.EditorDocument.attachEvent("ondblclick", Doc_OnDblClick ) ; 
     153         
     154        //additions for table sizing 
     155        this.EditorDocument.attachEvent( 'onmousedown', Doc_OnMouseDown ) ; 
     156        this.EditorDocument.attachEvent( 'onmousemove', Doc_OnMouseMove ) ; 
     157         
    142158 
    143159        // Catch cursor selection changes. 
  • FCKeditor/branches/developers/mjk/editor/_source/internals/fckselection_gecko.js

    r132 r243  
    150150        return oSel ; 
    151151} 
     152 
     153// If FCKSelection is inside a table, return <td>'s so we can work on each 
     154// one as a separate element 
     155FCKSelection.TableNodes = function() 
     156{ 
     157        var oSel = FCK.EditorWindow.getSelection(); 
     158        var aNodes = new Array(); 
     159        if (this.HasAncestorNode("TABLE")) 
     160        { 
     161                var oTable = this.MoveToAncestorNode("TABLE"); 
     162                for (var r = 0; r < oTable.rows.length; r++) 
     163                { 
     164                        for (var c = 0; c < oTable.rows[r].cells.length; c++) 
     165                        { 
     166                                if (oSel.containsNode(oTable.rows[r].cells[c],true)) 
     167                                { 
     168                                        aNodes[aNodes.length] = oTable.rows[r].cells[c]; 
     169                                } 
     170                        } 
     171                } 
     172        } 
     173        return aNodes; 
     174} 
     175 
     176FCKSelection.SelectedHTML = function() 
     177{ 
     178        var oSel = FCK.EditorWindow.getSelection(); 
     179        var strHTML = ""; 
     180        //convert to a text range and walk the elements 
     181        for ( var i = 0 ; i < oSel.rangeCount ; i++ ) 
     182        { 
     183                var df = oSel.getRangeAt(i).cloneContents(); 
     184                 
     185                for (var j = 0; j < df.childNodes.length; j++) 
     186                { 
     187                        if (df.childNodes[j].nodeName == "#text") 
     188                                {if (df.childNodes[j].textContent) strHTML += df.childNodes[j].textContent;} 
     189                        else 
     190                                strHTML += '<' + df.childNodes[j].nodeName + '>' 
     191                                                + df.childNodes[j].innerHTML 
     192                                                + '</' + df.childNodes[j].nodeName + '>'; 
     193                } 
     194        } 
     195        return strHTML; 
     196} 
     197 
  • FCKeditor/branches/developers/mjk/editor/_source/internals/fckselection_ie.js

    r148 r243  
    4646        { 
    4747                case 'Control' : 
     48                        if (!FCKSelection.GetSelectedElement()) return; 
    4849                        return FCKSelection.GetSelectedElement().parentElement ; 
    4950                case 'None' : 
     
    110111} 
    111112 
     113// If FCKSelection is inside a table, return <td>'s so we can work on each 
     114// one as a separate element 
     115FCKSelection.TableNodes = function() 
     116{ 
     117        var oRange = FCK.EditorDocument.selection.createRange() ; 
     118        if (!oRange.htmlText.search(/<TD /)) return; 
     119        var oCellRange = oRange.duplicate(); 
     120        var oTable = this.MoveToAncestorNode("TABLE"); 
     121        if (!oTable) return; 
     122        var aNodes = new Array(); 
     123        for (var i = 0; i < oTable.cells.length; i++) 
     124        { 
     125                oCellRange.moveToElementText(oTable.cells[i]); 
     126                if (oRange.inRange(oCellRange)) 
     127                { 
     128                        aNodes[aNodes.length] = oTable.cells[i]; 
     129                } 
     130        } 
     131        return aNodes; 
     132} 
     133 
    112134// The "nodeTagName" parameter must be UPPER CASE. 
    113135FCKSelection.MoveToAncestorNode = function( nodeTagName ) 
     
    156178} 
    157179 
     180FCKSelection.SelectedHTML = function() 
     181{ 
     182        return FCK.EditorDocument.selection.createRange().htmlText; 
     183} 
    158184 
     185 
  • FCKeditor/branches/developers/mjk/editor/_source/internals/fckselection.js

    r132 r243  
    2323 
    2424var FCKSelection = FCK.Selection = new Object() ; 
     25 
     26//Return the nearest ancestor to the current position of the caret. 
     27FCKSelection.GetCaretAncestor = function(strTag) 
     28{ 
     29        var e = FCKSelection.GetParentElement(); 
     30        var tn = e ?    FCKTools.GetElementAscensor(e,strTag) : 
     31                                        FCKSelection.MoveToAncestorNode(strTag); 
     32        return tn; 
     33} 
     34 
     35FCKSelection.SelectedText = function() 
     36{ 
     37        return FCKTools.HTMLToText( this.SelectedHTML() ); 
     38} 
  • FCKeditor/branches/developers/mjk/editor/_source/internals/fcktablehandler.js

    r132 r243  
    11/* 
    22 * FCKeditor - The text editor for Internet - http://www.fckeditor.net 
    3  * Copyright (C) 2003-2007 Frederico Caldeira Knabben 
     3 * Copyright ( C ) 2003-2007 Frederico Caldeira Knabben 
    44 * 
    55 * == BEGIN LICENSE == 
     
    88 * choice: 
    99 * 
    10  *  - GNU General Public License Version 2 or later (the "GPL") 
     10 *  - GNU General Public License Version 2 or later ( the "GPL" ) 
    1111 *    http://www.gnu.org/licenses/gpl.html 
    1212 * 
    13  *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL") 
     13 *  - GNU Lesser General Public License Version 2.1 or later ( the "LGPL" ) 
    1414 *    http://www.gnu.org/licenses/lgpl.html 
    1515 * 
    16  *  - Mozilla Public License Version 1.1 or later (the "MPL") 
     16 *  - Mozilla Public License Version 1.1 or later ( the "MPL" ) 
    1717 *    http://www.mozilla.org/MPL/MPL-1.1.html 
    1818 * 
     
    4242FCKTableHandler.DeleteRows = function( row ) 
    4343{ 
    44         // If no row has been passed as a parameter, 
    45         // then get the row where the selection is placed in. 
    46         if ( !row ) 
    47                 row = FCKSelection.MoveToAncestorNode( 'TR' ) ; 
    48         if ( !row ) return ; 
     44        // If no row has been passed as a parameer, 
     45        // then get the row( s ) containing the cells where the selection is placed in.  
     46        // If user selected multiple rows ( by selecting multiple cells ), walk 
     47        // the selected cell list and delete the rows containing the selected cells 
     48        if ( !row  ) 
     49        { 
     50                var aCells = FCKTableHandler.GetSelectedCells(); 
     51                var aRowsToDelete = new Array(); 
     52                //queue up the rows -- it's possible ( and likely ) that we may get duplicates 
     53                for ( var i = 0; i < aCells.length; i++  ) 
     54                { 
     55                        var oRow = FCKTools.GetElementAscensor( aCells[i],'TR'  ); 
     56                        aRowsToDelete[oRow.rowIndex] = oRow; 
     57                } 
     58                for ( var i = aRowsToDelete.length; i >= 0; i--  ) 
     59                { 
     60                        if ( aRowsToDelete[i]  ) 
     61                                FCKTableHandler.DeleteRows( aRowsToDelete[i] ); 
     62                } 
     63        } 
     64        if ( !row  ) return ; 
    4965 
    5066        // Get the row's table. 
     
    7793        FCKSelection.SelectNode( table ) ; 
    7894        FCKSelection.Collapse(); 
    79         table.parentNode.removeChild( table ) ; 
     95         
     96        // if the table is wrapped with a singleton <p> ( or something similar ), remove 
     97        // the surrounding tag -- which likely won't show after deletion anyway 
     98        if ( table.parentNode.children.length == 1 ) 
     99                table.parentNode.parentNode.removeChild( table.parentNode ); 
     100        else 
     101                table.parentNode.removeChild( table  ) ; 
    80102} 
    81103 
     
    83105{ 
    84106        // Get the cell where the selection is placed in. 
    85         var oCell = FCKSelection.MoveToAncestorNode('TD') || FCKSelection.MoveToAncestorNode('TH') ; 
     107        var oCell = FCKSelection.MoveToAncestorNode( 'TD' ) || FCKSelection.MoveToAncestorNode( 'TH' ) ; 
    86108 
    87109        if ( !oCell ) return ; 
     
    103125                        continue ; 
    104126 
    105                 oCell = oRow.cells[iIndex-1].cloneNode(false) ; 
     127                oCell = oRow.cells[iIndex-1].cloneNode( false ) ; 
    106128 
    107129                if ( FCKBrowserInfo.IsGecko ) 
     
    119141} 
    120142 
    121 FCKTableHandler.DeleteColumns = function() 
    122 { 
    123         // Get the cell where the selection is placed in. 
    124         var oCell = FCKSelection.MoveToAncestorNode('TD') || FCKSelection.MoveToAncestorNode('TH') ; 
     143FCKTableHandler.DeleteColumns = function( oCell ) 
     144{ 
     145        // if user selected multiple cols ( by selecting multiple cells ), walk 
     146        // the selected cell list and delete the rows containing the selected cells 
     147        if ( !oCell  ) 
     148        { 
     149                var aColsToDelete = FCKTableHandler.GetSelectedCells(); 
     150                for ( var i = aColsToDelete.length; i >= 0; i--  ) 
     151                { 
     152                        if ( aColsToDelete[i]  ) 
     153                                FCKTableHandler.DeleteColumns( aColsToDelete[i]  ); 
     154                } 
     155                return; 
     156        } 
    125157 
    126158        if ( !oCell ) return ; 
     
    300332                        return c ; 
    301333        } 
    302  
     334         
     335        return null ; 
     336} 
     337 
     338// Get the cell location from a TableMap. Returns an array with an [x,y] location 
     339FCKTableHandler._GetCellLocation = function( tableMap, cell  ) 
     340{ 
     341        for ( var i = 0 ; i < tableMap.length; i++ ) 
     342        { 
     343                for ( var c = 0 ; c < tableMap[i].length ; c++  ) 
     344                { 
     345                        if ( tableMap[i][c] == cell  ) return [i,c]; 
     346                } 
     347        } 
    303348        return null ; 
    304349} 
     
    384429        } 
    385430} 
     431 
     432//Returns TRUE if any cell has width set 
     433FCKTableHandler.HasCellWidths = function( table ) 
     434{ 
     435        for ( var r = 0; r < table.rows.length; r++ ) 
     436        { 
     437                for ( var c = 0; c < table.rows[r].cells.length; c++ ) 
     438                { 
     439                        if ( table.rows[r].cells[c].width ) return true; 
     440                } 
     441        } 
     442        return false; 
     443} 
     444 
     445//Clears all cell widths/heights ( letting the browser size everything ) 
     446FCKTableHandler.ClearCellWidths = function( table ) 
     447{ 
     448        for ( var r = 0; r < table.rows.length; r++ ) 
     449        { 
     450                for ( var c = 0; c < table.rows[r].cells.length; c++ ) 
     451                { 
     452                        table.rows[r].cells[c].width = ""; 
     453                        table.rows[r].cells[c].height = ""; 
     454                        table.rows[r].cells[c].removeAttribute( "WIDTH" ); 
     455                        table.rows[r].cells[c].removeAttribute( "HEIGHT" ); 
     456                } 
     457        } 
     458} 
     459 
     460//Cleanup table widths. If bPercent, recalculates table widths in %. If bClear, 
     461//moves all table widths as early as possible 
     462 
     463FCKTableHandler.CleanupTableWidths = function( table, bPercent, bClear, aMapIn ) 
     464{ 
     465        var aMap = aMapIn ? aMapIn : this._CreateTableMap( table ) ; 
     466        var nCols = aMap[0].length; 
     467        var nRows = aMap.length; 
     468        var nTotalWidth = 0; 
     469        var aSizeCells = new Array(); 
     470        var aSizes = new Array(); 
     471        //work the table column-by-column 
     472        for ( var nCol = 0; nCol < nCols; nCol++ ) 
     473        { 
     474                var nMax = 0; 
     475                var oCell = null; 
     476                //walk the rows for a specific column -- find the topmost non-colspan'd item 
     477                //and the maximum pixel width ( according to the browser ) 
     478                for ( var nRow = 0; nRow < nRows; nRow++ ) 
     479                { 
     480                        if ( aMap[nRow][nCol].colSpan > 1 ) continue; 
     481                        //use topmost non-colspan'd cell to put the width in 
     482                        if ( !oCell ) oCell = aMap[nRow][nCol]; 
     483                        if ( aMap[nRow][nCol].offsetWidth > nMax ) nMax = aMap[nRow][nCol].offsetWidth; 
     484                } 
     485                aSizes[nCol] = nMax; 
     486                nTotalWidth += nMax; 
     487                aSizeCells[nCol] = oCell; 
     488        } 
     489        //if we were asked for percentage width, go through and convert the sizes to %. note 
     490        //that we do this based on the calculated width of all the cells; this is more 
     491        //reliable because offsetWidth, et al., includes table borders, padding, etc. 
     492        for ( var nCol = 0; nCol < aSizeCells.length; nCol++ ) 
     493        { 
     494                if ( bPercent ) 
     495                { 
     496                        var nWidth = Math.round( 100 * (aSizeCells[nCol].offsetWidth/nTotalWidth )); 
     497                        if ( nWidth == 0 ) nWidth = 1; 
     498                        strWidth =  nWidth + "%"; 
     499                } 
     500                else 
     501                { 
     502                        strWidth =  aSizes[nCol]; 
     503                } 
     504 
     505                //set all width attributes 
     506                for ( var nRow = 0; nRow < nRows; nRow++ ) 
     507                { 
     508                        if ( aMap[nRow][nCol].colSpan == 1 ) 
     509                        { 
     510                                aMap[nRow][nCol].width = bClear ? '' : strWidth; 
     511                                if ( bClear ) aMap[nRow][nCol].removeAttribute( "width" ); 
     512                                aSizeCells[nCol].width = strWidth; 
     513                        } 
     514                } 
     515        } 
     516} 
     517 
     518// Move the cursor into the next ( or previous ) cell 
     519FCKTableHandler.MoveToNextCell = function( bRev ) 
     520{ 
     521        var aCells = FCKTableHandler.GetSelectedCells(); 
     522        if ( aCells.length == 0 ) return; 
     523        var oCell = aCells[0]; 
     524        var oNextCell = bRev ? oCell.previousSibling: oCell.nextSibling; 
     525        if ( !oNextCell ) 
     526        { 
     527                var oNext; 
     528                var oRow = FCKTools.GetElementAscensor( oCell,"TR" ); 
     529                if ( bRev ) 
     530                { 
     531                        if ( !(oNext = oRow.previousSibling )) return; 
     532                        oNextCell=oNext.cells[oNext.cells.length - 1]; 
     533                } 
     534                else 
     535                { 
     536                        if ( !(oNext = oRow.nextSibling )) return; 
     537                        oNextCell=oNext.cells[0]; 
     538                } 
     539        } 
     540        FCKSelection.SelectNode( oNextCell ); 
     541        FCKSelection.Collapse(); 
     542} 
     543////////////////////////////////////////////////////////////////// 
     544// Table Sizer 
     545// 
     546 
     547 
     548// Returns the closest sizeable cell to point (or the left of the specified point 
     549// if between cells). Generally, this will be a heading cell (i.e. a cell in 
     550// the first row). If *all* the candidate cells are colspan'd (heaven forbid), 
     551// don't allow sizing. x and y are in client coordinates 
     552 
     553FCKTableHandler.SizableCellFromPoint = function( table, ncx, ncy ) 
     554{ 
     555        var aRows = table.rows ; 
     556        var x = ncx - this._CalcPosition( table )[0]; 
     557        for ( var i = 0 ; i < aRows.length ; i++  ) 
     558        { 
     559                for ( var j = 0; j < aRows[i].cells.length - 1; j++ ) 
     560                { 
     561                        if ( aRows[i].cells[j + 1].offsetLeft > x ) 
     562                        { 
     563                                if ( aRows[i].cells[j].colSpan < 2 ) 
     564                                { 
     565                                        return aRows[i].cells[j]; 
     566                                } 
     567                                else 
     568                                { 
     569                                        break; 
     570                                } 
     571                        }        
     572                } 
     573        } 
     574        return null; 
     575} 
     576 
     577// Creates the table resize bar. If a table resize bar is present, uses it. You 
     578// must explicitly destroy the table resize bar with DestroyResizeBar after use. 
     579FCKTableHandler.CreateResizeBar = function() 
     580{ 
     581        if ( this.ResizeBar ) return this.ResizeBar; 
     582        var oBar;        
     583        oBar = FCK.EditorDocument.createElement( "SPAN" ); 
     584 
     585        // setup the bar 
     586        oBar.id = '__FCKResizeBar'; 
     587        oBar.style.position = "absolute"; 
     588        oBar.style.top = "0px"; 
     589        oBar.style.left = "0px"; 
     590        oBar.style.height = "0px"; 
     591        oBar.style.width = "2px"; 
     592        oBar.style.borderLeft = "1px solid #0033FF"; 
     593        oBar.style.display = "none"; 
     594        oBar.style.cursor = "e-resize"; 
     595 
     596        FCK.EditorDocument.body.appendChild( oBar ); 
     597        this.ResizeBar = oBar; 
     598        return oBar; 
     599} 
     600 
     601// Destroys the table resize bar 
     602FCKTableHandler.DestroyResizeBar = function() 
     603{ 
     604        if ( !this.ResizeBar ) return; 
     605        this.ResizeBar.parentNode.removeChild( FCKTableHandler.ResizeBar ); 
     606        this.ResizeBar = null; 
     607} 
     608 
     609// Figures out whether we want to size or let the browser do its thing. We can 
     610// size if the table is the target and we're between cells, OR if we're on 
     611// a table cell and on the far right edge of the cell within 3px of the edge 
     612// ( allows us to easily size tables with thin borders ) 
     613 
     614FCKTableHandler.CanSizeHere = function( ev, cell, tbl ) 
     615{ 
     616        var elem = ev.srcElement || ev.originalTarget; 
     617        var aCellLoc = this._CalcPosition( cell ); 
     618        var aTableLoc = this._CalcPosition( tbl ); 
     619        //in the td client area, but not on the edge 
     620        if ( elem != tbl ) return ( (aCellLoc[0] + cell.offsetWidth - ev.clientX ) < 3); 
     621        //on the table edge 
     622        if ( (aTableLoc[0] + tbl.offsetWidth - ev.clientX ) < 3 || 
     623                ( aTableLoc[0] - ev.clientX ) < 3 || 
     624                ( aTableLoc[1] + tbl.offsetHeight - ev.clientY < 3 ) || 
     625                ( aTableLoc[1] - ev.clientY < 3 )) return false; 
     626        return true; 
     627} 
     628 
     629 
     630// Sets up table sizing 
     631FCKTableHandler.StartTableSizing = function( ev, cell, tbl ) 
     632{ 
     633        if ( !cell ) return null; 
     634        this.tableMap = this._CreateTableMap( tbl ) ; 
     635        var aCellLoc = this._GetCellLocation( this.tableMap, cell );                            //returns [row,col] 
     636        if ( !aCellLoc ) return null; 
     637        //we're in the last column, so we can't size 
     638        if ( aCellLoc[1] == this.tableMap[aCellLoc[0]].length - 1 ) return null; 
     639        var nTarget = aCellLoc[1] + 1; 
     640        this.adjacentCell = null; 
     641        for ( var i=0; i < this.tableMap.length; i++ ) 
     642        { 
     643                if ( this.tableMap[i][nTarget].colSpan < 2 ) 
     644                { 
     645                        this.adjacentCell = this.tableMap[i][nTarget]; 
     646                        break; 
     647                } 
     648        } 
     649        if ( this.adjacentCell == null ) return null;   //can't size, no adjacent col 
     650        this.targetCell = cell; 
     651        //ok. we have everything we need. off we go. 
     652         
     653        //create the resize bar 
     654        this.pixWidths = !( this.targetCell.width.search('%' ) == -1 || !this.targetCell.width); 
     655        var oVBar = this.CreateResizeBar(); 
     656        //oVBar.style.left = FCK.EditorDocument.body.scrollLeft + this._CalcPosition( cell ) + cell.offsetWidth; 
     657        //this.origPos = FCK.EditorDocument.body.scrollLeft + ev.clientX; 
     658        this.origPos = FCK.EditorDocument.body.scrollLeft + this._CalcPosition( cell )[0] + cell.offsetWidth; 
     659        oVBar.style.left = this.origPos; 
     660        oVBar.style.cursor = "e-resize"; 
     661        oVBar.setAttribute( "UNSELECTABLE","on" ); 
     662        tbl.setAttribute( "UNSELECTABLE","on" ); 
     663        this.sizeOffset = ev.clientX - this.origPos; 
     664        //minimum size is always the left edge of the cell + some safety margin. 
     665        //max size is always the right edge of the next cell - some safety margin 
     666        this.minSize = FCK.EditorDocument.body.scrollLeft + this._CalcPosition( cell )[0] + 10; 
     667        this.maxSize = FCK.EditorDocument.body.scrollLeft + this._CalcPosition( this.adjacentCell )[0] + this.adjacentCell.offsetWidth - 10; 
     668        oVBar.style.top = this._CalcPosition( tbl )[1]; 
     669        oVBar.style.height = tbl.clientHeight + ( tbl.border*2 ); 
     670        oVBar.style.display = "inline"; 
     671        this.CleanupTableWidths( tbl,false, true,this.tableMap ); 
     672        return true; 
     673} 
     674 
     675FCKTableHandler.FinishTableSizing = function() 
     676{ 
     677        var tbl = FCKTools.GetElementAscensor( this.targetCell,"TABLE" ); 
     678        var nTargetDiff = this.ResizeBar.offsetLeft - this.origPos; 
     679        //widths are in pixels after StartTableSizing, so this is safe 
     680        tbl.style.cursor = ''; 
     681        if ( tbl.runtimeStyle ) tbl.runtimeStyle.cursor = ''; 
     682        this.targetCell.width = parseInt( this.targetCell.width ) + nTargetDiff; 
     683        this.adjacentCell.width = parseInt( this.adjacentCell.width ) - nTargetDiff; 
     684        this.DestroyResizeBar(); 
     685        this.CleanupTableWidths( tbl,this.pixWidths,true,this.tableMap ); 
     686        this.targetCell = null; 
     687        this.origPos = null; 
     688        tbl.removeAttribute( "UNSELECTABLE" ); 
     689        if ( FCKBrowserInfo.IsGecko  ) tbl.style.MozUserSelect = ""; 
     690} 
     691 
     692// Sizes the table to the given mouse position 
     693FCKTableHandler.SizeTo = function( x ) 
     694{ 
     695        var nPos = x - this.sizeOffset; 
     696        if ( nPos > this.maxSize ) nPos = this.maxSize; 
     697        if ( nPos < this.minSize ) nPos = this.minSize; 
     698        //runtimeStyle is way faster under IE 
     699        if ( this.ResizeBar.runtimeStyle ) 
     700                this.ResizeBar.runtimeStyle.left = nPos; 
     701        else 
     702                this.ResizeBar.style.left = nPos; 
     703        if ( FCKBrowserInfo.IsGecko && FCK.EditorDocument.selection.type != 'None' ) FCK.EditorDocument.selection.collapse(); 
     704} 
     705 
     706// returns TRUE if we are actively sizing a table 
     707FCKTableHandler.IsTableSizing = function() 
     708{ 
     709        return ( this.targetCell != null ); 
     710} 
     711 
     712// figure out where ( with respect to the edge of the parent ) a given table/cell is 
     713FCKTableHandler._CalcPosition = function( ob ) 
     714{ 
     715        var oParent=ob; 
     716        var nY = 0; 
     717        var nX = 0; 
     718        while ( oParent && oParent.tagName != "BODY" ) 
     719        { 
     720                nX += oParent.offsetLeft; 
     721                nY += oParent.offsetTop; 
     722                oParent = oParent.offsetParent; 
     723        } 
     724        return [nX,nY]; 
     725} 
     726 
     727FCKTableHandler.tbl_MouseDown = function ( FCK, e ) 
     728{ 
     729        var elem = e.srcElement || e.originalTarget; 
     730        var strTag = elem ? elem.tagName.toUpperCase() : null; 
     731        //find the table we're part of, if we are 
     732        if ( elem && (strTag == 'TABLE' || strTag == 'TD' || strTag == 'TH' ) ) 
     733        { 
     734                FCKTableHandler.targetCell = null; 
     735                var oTable = FCKTools.GetElementAscensor( elem, "TABLE" ); 
     736                //figure out if there's a cell we can size 
     737                var oCell = FCKTableHandler.SizableCellFromPoint( oTable, e.clientX, e.clientY ); 
     738                if ( !oCell ) return true; 
     739                if ( FCKTableHandler.CanSizeHere( e,oCell,oTable ) ) 
     740                { 
     741                        if ( FCKTableHandler.StartTableSizing( e,oCell, oTable ) ) 
     742                        { 
     743                                if ( oTable.runtimeStyle ) oTable.runtimeStyle.cursor = "e-resize"; 
     744                                if ( FCKBrowserInfo.IsGecko  ) oTable.style.MozUserSelect = "none"; 
     745                                e.cancelBubble  = true ; 
     746                                e.returnValue   = false ; 
     747                                return false; 
     748                        } 
     749                } 
     750        } 
     751        return true; 
     752} 
     753 
     754FCKTableHandler.tbl_MouseUp = function ( FCK, e ) 
     755{ 
     756        if ( FCKTableHandler.IsTableSizing( )) FCKTableHandler.FinishTableSizing(); 
     757} 
     758 
     759FCKTableHandler.tbl_MouseMove = function ( FCK, e ) 
     760{ 
     761        var elem = e.srcElement || e.originalTarget; 
     762        if ( FCKTableHandler.IsTableSizing() ) 
     763        { 
     764                FCKTableHandler.SizeTo( e.clientX ); 
     765                e.cancelBubble  = true ; 
     766                e.returnValue   = false ; 
     767                return false; 
     768        } 
     769         
     770        if ( elem.tagName.toUpperCase() == 'TABLE' ) 
     771        { 
     772                //let the browser handle global sizing and move if the user is on 
     773                //the RH edge of a table 
     774                if ( elem.clientWidth - e.offsetX < 3 || 
     775                        elem.clientHeight - e.offsetY < 3 || 
     776                        e.offsetX < 2 || e.offsetY < 2 ) 
     777                { 
     778                        elem.style.cursor = "";  
     779                        return true; 
     780                } 
     781                //block browser sizing -- we're going to do it ourselves, thanks 
     782                if ( elem.runtimeStyle ) elem.runtimeStyle.cursor = "e-resize"; 
     783                e.cancelBubble  = true ; 
     784                e.returnValue   = false ; 
     785                return false; 
     786        } 
     787        else if ( elem.tagName.toUpperCase() == 'TD' ) 
     788        { 
     789            var tbl = FCKTools.GetElementAscensor( elem, "TABLE" ); 
     790                if ( e.offsetX >= (elem.offsetWidth - 4 )) 
     791                { 
     792                        e.cancelBubble  = true ; 
     793                        e.returnValue   = false ; 
     794                        return false; 
     795            } 
     796        } 
     797        return true; 
     798} 
     799 
     800FCK.Events.AttachEvent( "OnMouseMove", FCKTableHandler.tbl_MouseMove ); 
     801FCK.Events.AttachEvent( "OnMouseDown", FCKTableHandler.tbl_MouseDown ); 
     802FCK.Events.AttachEvent( "OnMouseUp", FCKTableHandler.tbl_MouseUp ); 
  • FCKeditor/branches/developers/mjk/editor/_source/internals/fcktools.js

    r146 r243  
    9494 
    9595        return text ; 
     96} 
     97 
     98//convert text to Proper Case 
     99FCKTools.ProperCase = function( text ) 
     100{ 
     101        var strPC = text.toLowerCase(); 
     102        return strPC.replace(/(\S)(\S*\s*)/g, 
     103                                                function(str,p1,p2)  
     104                                                        {return p1.toUpperCase()+p2}); 
     105} 
     106 
     107FCKTools.HTMLToText = function( st ) 
     108{ 
     109        if ( !st )  
     110                return null; 
     111                 
     112        st = st.replace(/<([^>]*?)>/g,''); 
     113        st = st.replace(/&nbsp;/gi,' '); 
     114        return st; 
    96115} 
    97116