Changeset 4353

Show
Ignore:
Timestamp:
09/27/08 13:53:17 (3 months ago)
Author:
jun66j5
Message:
  • fixed #3399 - handle pressing tab
    • in list, execute indent/outdent.
    • in table, move focus to next/previous cell.
    • in pre, insert a tab.
  • auto format-paragraph.
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • tracwysiwygplugin/0.10/tracwysiwyg/htdocs/wysiwyg.js

    r4214 r4353  
    438438 
    439439TracWysiwyg.prototype.setupEditorEvents = function() { 
     440    var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; 
    440441    var self = this; 
    441442    var d = this.contentDocument; 
     
    447448        var args = null; 
    448449        event = event || self.contentWindow.event; 
    449         if (event.keyCode == 0xe5) { 
     450        var keyCode = event.keyCode; 
     451        switch (keyCode) { 
     452        case 0x09:  // TAB 
     453            var range = self.getSelectionRange(); 
     454            var element = getSelfOrAncestor(range.startContainer, /^(?:li|pre|table)$/); 
     455            if (element) { 
     456                switch (element.tagName.toLowerCase()) { 
     457                case "li": 
     458                    self.execCommand(event.shiftKey ? "outdent" : "indent"); 
     459                    self.selectionChanged(); 
     460                    break; 
     461                case "pre": 
     462                    self.insertHTML("\t"); 
     463                    break; 
     464                case "table": 
     465                    if (getSelfOrAncestor(range.endContainer, "table") == element) { 
     466                        self.moveFocusInTable(!event.shiftKey); 
     467                        self.selectionChanged(); 
     468                    } 
     469                    break; 
     470                } 
     471            } 
     472            TracWysiwyg.stopEvent(event); 
     473            return; 
     474        case 0xe5: 
    450475            ime = true; 
    451         } 
    452         switch ((event.keyCode & 0x00fffff) | (event.ctrlKey ? 0x40000000 : 0) 
     476            break; 
     477        } 
     478        switch ((keyCode & 0x00fffff) | (event.ctrlKey ? 0x40000000 : 0) 
    453479            | (event.shiftKey ? 0x20000000 : 0) | (event.altKey ? 0x10000000 : 0)) 
    454480        { 
     
    483509            self.selectionChanged(); 
    484510        } 
     511        else if (keyCode) { 
     512            var focus = self.getFocusNode(); 
     513            if (!getSelfOrAncestor(focus, /^(?:p|li|h[1-6]|t[dh]|d[td]|pre|blockquote)$/)) { 
     514                self.execCommand("formatblock", "<p>"); 
     515            } 
     516        } 
    485517    } 
    486518    addEvent(d, window.opera ? "keypress" : "keydown", listenerKeydown); 
     
    548580    } 
    549581    var fragment = this.wikitextToFragment(this.textarea.value, d); 
    550     if (fragment.childNodes.length == 0) { 
    551         var paragraph = d.createElement("p"); 
    552         this.appendBogusLineBreak(paragraph); 
    553         fragment.appendChild(paragraph); 
    554     } 
    555582    container.appendChild(fragment); 
    556583    this.savedWysiwygHTML = container.innerHTML; 
     
    874901            if (cellIndex < row.cells.length) { 
    875902                row.deleteCell(cellIndex); 
     903            } 
     904        } 
     905    } 
     906}; 
     907 
     908TracWysiwyg.prototype.moveFocusInTable = function(forward) { 
     909    var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; 
     910    var focus = this.getFocusNode(); 
     911    var element = getSelfOrAncestor(focus, /^(?:t[dhr]|table)$/); 
     912    var target, table, rows, cells; 
     913    switch (element.tagName.toLowerCase()) { 
     914    case "td": case "th": 
     915        focus = element; 
     916        var row = getSelfOrAncestor(element, "tr"); 
     917        cells = row.cells; 
     918        if (forward) { 
     919            if (focus.cellIndex + 1 < cells.length) { 
     920                target = cells[focus.cellIndex + 1]; 
     921            } 
     922            else { 
     923                table = getSelfOrAncestor(row, /^(?:tbody|table)$/); 
     924                rows = table.rows; 
     925                target = row.rowIndex + 1 < rows.length ? rows[row.rowIndex + 1].cells[0] : null; 
     926            } 
     927        } 
     928        else { 
     929            if (focus.cellIndex > 0) { 
     930                target = cells[focus.cellIndex - 1]; 
     931            } 
     932            else { 
     933                table = getSelfOrAncestor(row, /^(?:tbody|table)$/); 
     934                rows = table.rows; 
     935                if (row.rowIndex > 0) { 
     936                    cells = rows[row.rowIndex - 1].cells; 
     937                    target = cells[cells.length - 1]; 
     938                } 
     939                else { 
     940                    target = null; 
     941                } 
     942            } 
     943        } 
     944        break; 
     945    case "tr": 
     946        cells = element.cells; 
     947        target = cells[forward ? 0 : cells.length - 1]; 
     948        break; 
     949    case "tbody": case "table": 
     950        rows = element.rows; 
     951        cells = rows[forward ? 0 : rows.length - 1].cells; 
     952        target = cells[forward ? 0 : cells.length - 1]; 
     953        break; 
     954    } 
     955    if (target) { 
     956        this.selectNodeContents(target); 
     957    } 
     958    else if (table) { 
     959        table = getSelfOrAncestor(table, "table"); 
     960        var parent = table.parentNode; 
     961        var elements = parent.childNodes; 
     962        var length = elements.length; 
     963        for (var offset = 0; offset < length; offset++) { 
     964            if (table == elements[offset]) { 
     965                if (forward) { 
     966                    offset++; 
     967                } 
     968                this.selectRange(parent, offset, parent, offset); 
    876969            } 
    877970        } 
     
    29733066        var body = d.body; 
    29743067        d.selection.empty(); 
     3068        var range = endPoint(start, startOffset); 
     3069        if (start != end || startOffset != endOffset) { 
     3070            range.setEndPoint("EndToEnd", endPoint(end, endOffset)); 
     3071        } 
     3072        range.select(); 
    29753073 
    29763074        function endPoint(node, offset) { 
    2977             var range = body.createTextRange(); 
    2978             var childNodes = node.childNodes; 
     3075            var range; 
    29793076            if (node.nodeType == 1) { 
     3077                var childNodes = node.childNodes; 
    29803078                if (offset >= childNodes.length) { 
     3079                    range = body.createTextRange(); 
    29813080                    range.moveToElementText(node); 
    29823081                    range.collapse(false); 
     
    29853084                node = childNodes[offset]; 
    29863085                if (node.nodeType == 1) { 
     3086                    range = body.createTextRange(); 
    29873087                    range.moveToElementText(node); 
    29883088                    range.collapse(true); 
     3089                    switch (node.tagName.toLowerCase()) { 
     3090                    case "table": 
     3091                        range.move("character", -1); 
     3092                        break; 
     3093                    } 
    29893094                    return range; 
    29903095                } 
     
    29953100            } 
    29963101 
     3102            range = body.createTextRange(); 
    29973103            var element = node.previousSibling; 
    29983104            while (element) { 
     
    30123118                range.collapse(true); 
    30133119            } 
    3014             range.move("character", offset); 
     3120            if (offset != 0) { 
     3121                range.move("character", offset); 
     3122            } 
    30153123            return range; 
    30163124        } 
    3017  
    3018         var range = body.createTextRange(); 
    3019         range.setEndPoint("StartToStart", endPoint(start, startOffset)); 
    3020         range.setEndPoint("EndToEnd", endPoint(end, endOffset)); 
    3021         range.select(); 
    30223125    }; 
    30233126    TracWysiwyg.prototype.getSelectionRange = function() { 
    30243127        var body = this.contentDocument.body; 
     3128        var pseudo = {}; 
    30253129        var start = this.getNativeSelectionRange(); 
     3130        if (start.item) { 
     3131            var element = start.item(0); 
     3132            var parent = element.parentNode; 
     3133            var childNodes = parent.childNodes; 
     3134            var length = childNodes.length; 
     3135            for (var i = 0; i < length; i++) { 
     3136                if (childNodes[i] == element) { 
     3137                    pseudo.startOffset = i; 
     3138                    pseudo.endOffset = i + 1; 
     3139                    break; 
     3140                } 
     3141            } 
     3142            pseudo.collapsed = false; 
     3143            pseudo.startContainer = pseudo.endContainer = parent; 
     3144            return pseudo; 
     3145        } 
    30263146        var end = start.duplicate(); 
    3027         var pseudo = {}; 
    30283147        pseudo.collapsed = start.compareEndPoints("StartToEnd", end) == 0; 
    30293148        start.collapse(true); 
     
    30693188            var index = 0; 
    30703189            var node = element ? element.previousSibling : parent.lastChild; 
    3071             while (node.nodeType == 3) { 
    3072                 var length = node.nodeValue.length; 
    3073                 var offset = nodeOffset(range, parent, element, index, length); 
     3190            var offset, length; 
     3191            while (node && node.nodeType == 3) { 
     3192                length = node.nodeValue.length; 
     3193                offset = nodeOffset(range, parent, element, index, length); 
    30743194                if (offset !== null) { 
    30753195                    pseudo[containerKey] = node; 
     
    30793199                index += length; 
    30803200                node = node.previousSibling; 
     3201            } 
     3202            var childNodes = parent.childNodes; 
     3203            length = childNodes.length; 
     3204            if (length > 0) { 
     3205                pseudo[containerKey] = parent; 
     3206                pseudo[offsetKey] = containerKey == "startContainer" ? 0 : length - 1; 
     3207                return; 
     3208            } 
     3209            element = parent; 
     3210            parent = element.parentNode; 
     3211            childNodes = parent.childNodes; 
     3212            length = childNodes.length; 
     3213            for (offset = 0; offset < length; offset++) { 
     3214                if (element == childNodes[offset]) { 
     3215                    pseudo[containerKey] = parent; 
     3216                    pseudo[offsetKey] = offset; 
     3217                    return; 
     3218                } 
    30813219            } 
    30823220        } 
     
    30873225    }; 
    30883226    TracWysiwyg.prototype.getNativeSelectionRange = function() { 
    3089         var range = this.contentDocument.selection.createRange(); 
    3090         if (range && range.item) { 
    3091             range = range.item(0); 
    3092         } 
    3093         return range; 
     3227        return this.contentDocument.selection.createRange(); 
    30943228    }; 
    30953229    TracWysiwyg.prototype.getSelectionText = function() { 
    30963230        var range = this.getNativeSelectionRange(); 
    3097         return range ? range.text : null; 
     3231        if (range) { 
     3232            return range.item ? range.item(0).innerText : range.text; 
     3233        } 
     3234        return null; 
    30983235    }; 
    30993236    TracWysiwyg.prototype.getSelectionHTML = function() { 
    31003237        var range = this.getNativeSelectionRange(); 
    3101         return range ? range.htmlText : null; 
     3238        if (range) { 
     3239            return range.item ? range.item(0).innerHTML : range.htmlText; 
     3240        } 
     3241        return null; 
    31023242    }; 
    31033243    TracWysiwyg.prototype.getSelectionFragment = function() { 
     
    31793319    TracWysiwyg.prototype.insertHTML = function(html) { 
    31803320        var range = this.contentDocument.selection.createRange(); 
    3181         range.pasteHTML(html); 
     3321        if (/^\s+$/.exec(html)) { 
     3322            range.text = html; 
     3323        } 
     3324        else { 
     3325            range.pasteHTML(html.replace(/\t/g, "&#9;")); 
     3326        } 
    31823327    }; 
    31833328} 
  • tracwysiwygplugin/0.11/tracwysiwyg/htdocs/wysiwyg.js

    r4214 r4353  
    438438 
    439439TracWysiwyg.prototype.setupEditorEvents = function() { 
     440    var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; 
    440441    var self = this; 
    441442    var d = this.contentDocument; 
     
    447448        var args = null; 
    448449        event = event || self.contentWindow.event; 
    449         if (event.keyCode == 0xe5) { 
     450        var keyCode = event.keyCode; 
     451        switch (keyCode) { 
     452        case 0x09:  // TAB 
     453            var range = self.getSelectionRange(); 
     454            var element = getSelfOrAncestor(range.startContainer, /^(?:li|pre|table)$/); 
     455            if (element) { 
     456                switch (element.tagName.toLowerCase()) { 
     457                case "li": 
     458                    self.execCommand(event.shiftKey ? "outdent" : "indent"); 
     459                    self.selectionChanged(); 
     460                    break; 
     461                case "pre": 
     462                    self.insertHTML("\t"); 
     463                    break; 
     464                case "table": 
     465                    if (getSelfOrAncestor(range.endContainer, "table") == element) { 
     466                        self.moveFocusInTable(!event.shiftKey); 
     467                        self.selectionChanged(); 
     468                    } 
     469                    break; 
     470                } 
     471            } 
     472            TracWysiwyg.stopEvent(event); 
     473            return; 
     474        case 0xe5: 
    450475            ime = true; 
    451         } 
    452         switch ((event.keyCode & 0x00fffff) | (event.ctrlKey ? 0x40000000 : 0) 
     476            break; 
     477        } 
     478        switch ((keyCode & 0x00fffff) | (event.ctrlKey ? 0x40000000 : 0) 
    453479            | (event.shiftKey ? 0x20000000 : 0) | (event.altKey ? 0x10000000 : 0)) 
    454480        { 
     
    483509            self.selectionChanged(); 
    484510        } 
     511        else if (keyCode) { 
     512            var focus = self.getFocusNode(); 
     513            if (!getSelfOrAncestor(focus, /^(?:p|li|h[1-6]|t[dh]|d[td]|pre|blockquote)$/)) { 
     514                self.execCommand("formatblock", "<p>"); 
     515            } 
     516        } 
    485517    } 
    486518    addEvent(d, window.opera ? "keypress" : "keydown", listenerKeydown); 
     
    548580    } 
    549581    var fragment = this.wikitextToFragment(this.textarea.value, d); 
    550     if (fragment.childNodes.length == 0) { 
    551         var paragraph = d.createElement("p"); 
    552         this.appendBogusLineBreak(paragraph); 
    553         fragment.appendChild(paragraph); 
    554     } 
    555582    container.appendChild(fragment); 
    556583    this.savedWysiwygHTML = container.innerHTML; 
     
    874901            if (cellIndex < row.cells.length) { 
    875902                row.deleteCell(cellIndex); 
     903            } 
     904        } 
     905    } 
     906}; 
     907 
     908TracWysiwyg.prototype.moveFocusInTable = function(forward) { 
     909    var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; 
     910    var focus = this.getFocusNode(); 
     911    var element = getSelfOrAncestor(focus, /^(?:t[dhr]|table)$/); 
     912    var target, table, rows, cells; 
     913    switch (element.tagName.toLowerCase()) { 
     914    case "td": case "th": 
     915        focus = element; 
     916        var row = getSelfOrAncestor(element, "tr"); 
     917        cells = row.cells; 
     918        if (forward) { 
     919            if (focus.cellIndex + 1 < cells.length) { 
     920                target = cells[focus.cellIndex + 1]; 
     921            } 
     922            else { 
     923                table = getSelfOrAncestor(row, /^(?:tbody|table)$/); 
     924                rows = table.rows; 
     925                target = row.rowIndex + 1 < rows.length ? rows[row.rowIndex + 1].cells[0] : null; 
     926            } 
     927        } 
     928        else { 
     929            if (focus.cellIndex > 0) { 
     930                target = cells[focus.cellIndex - 1]; 
     931            } 
     932            else { 
     933                table = getSelfOrAncestor(row, /^(?:tbody|table)$/); 
     934                rows = table.rows; 
     935                if (row.rowIndex > 0) { 
     936                    cells = rows[row.rowIndex - 1].cells; 
     937                    target = cells[cells.length - 1]; 
     938                } 
     939                else { 
     940                    target = null; 
     941                } 
     942            } 
     943        } 
     944        break; 
     945    case "tr": 
     946        cells = element.cells; 
     947        target = cells[forward ? 0 : cells.length - 1]; 
     948        break; 
     949    case "tbody": case "table": 
     950        rows = element.rows; 
     951        cells = rows[forward ? 0 : rows.length - 1].cells; 
     952        target = cells[forward ? 0 : cells.length - 1]; 
     953        break; 
     954    } 
     955    if (target) { 
     956        this.selectNodeContents(target); 
     957    } 
     958    else if (table) { 
     959        table = getSelfOrAncestor(table, "table"); 
     960        var parent = table.parentNode; 
     961        var elements = parent.childNodes; 
     962        var length = elements.length; 
     963        for (var offset = 0; offset < length; offset++) { 
     964            if (table == elements[offset]) { 
     965                if (forward) { 
     966                    offset++; 
     967                } 
     968                this.selectRange(parent, offset, parent, offset); 
    876969            } 
    877970        } 
     
    29733066        var body = d.body; 
    29743067        d.selection.empty(); 
     3068        var range = endPoint(start, startOffset); 
     3069        if (start != end || startOffset != endOffset) { 
     3070            range.setEndPoint("EndToEnd", endPoint(end, endOffset)); 
     3071        } 
     3072        range.select(); 
    29753073 
    29763074        function endPoint(node, offset) { 
    2977             var range = body.createTextRange(); 
    2978             var childNodes = node.childNodes; 
     3075            var range; 
    29793076            if (node.nodeType == 1) { 
     3077                var childNodes = node.childNodes; 
    29803078                if (offset >= childNodes.length) { 
     3079                    range = body.createTextRange(); 
    29813080                    range.moveToElementText(node); 
    29823081                    range.collapse(false); 
     
    29853084                node = childNodes[offset]; 
    29863085                if (node.nodeType == 1) { 
     3086                    range = body.createTextRange(); 
    29873087                    range.moveToElementText(node); 
    29883088                    range.collapse(true); 
     3089                    switch (node.tagName.toLowerCase()) { 
     3090                    case "table": 
     3091                        range.move("character", -1); 
     3092                        break; 
     3093                    } 
    29893094                    return range; 
    29903095                } 
     
    29953100            } 
    29963101 
     3102            range = body.createTextRange(); 
    29973103            var element = node.previousSibling; 
    29983104            while (element) { 
     
    30123118                range.collapse(true); 
    30133119            } 
    3014             range.move("character", offset); 
     3120            if (offset != 0) { 
     3121                range.move("character", offset); 
     3122            } 
    30153123            return range; 
    30163124        } 
    3017  
    3018         var range = body.createTextRange(); 
    3019         range.setEndPoint("StartToStart", endPoint(start, startOffset)); 
    3020         range.setEndPoint("EndToEnd", endPoint(end, endOffset)); 
    3021         range.select(); 
    30223125    }; 
    30233126    TracWysiwyg.prototype.getSelectionRange = function() { 
    30243127        var body = this.contentDocument.body; 
     3128        var pseudo = {}; 
    30253129        var start = this.getNativeSelectionRange(); 
     3130        if (start.item) { 
     3131            var element = start.item(0); 
     3132            var parent = element.parentNode; 
     3133            var childNodes = parent.childNodes; 
     3134            var length = childNodes.length; 
     3135            for (var i = 0; i < length; i++) { 
     3136                if (childNodes[i] == element) { 
     3137                    pseudo.startOffset = i; 
     3138                    pseudo.endOffset = i + 1; 
     3139                    break; 
     3140                } 
     3141            } 
     3142            pseudo.collapsed = false; 
     3143            pseudo.startContainer = pseudo.endContainer = parent; 
     3144            return pseudo; 
     3145        } 
    30263146        var end = start.duplicate(); 
    3027         var pseudo = {}; 
    30283147        pseudo.collapsed = start.compareEndPoints("StartToEnd", end) == 0; 
    30293148        start.collapse(true); 
     
    30693188            var index = 0; 
    30703189            var node = element ? element.previousSibling : parent.lastChild; 
    3071             while (node.nodeType == 3) { 
    3072                 var length = node.nodeValue.length; 
    3073                 var offset = nodeOffset(range, parent, element, index, length); 
     3190            var offset, length; 
     3191            while (node && node.nodeType == 3) { 
     3192                length = node.nodeValue.length; 
     3193                offset = nodeOffset(range, parent, element, index, length); 
    30743194                if (offset !== null) { 
    30753195                    pseudo[containerKey] = node; 
     
    30793199                index += length; 
    30803200                node = node.previousSibling; 
     3201            } 
     3202            var childNodes = parent.childNodes; 
     3203            length = childNodes.length; 
     3204            if (length > 0) { 
     3205                pseudo[containerKey] = parent; 
     3206                pseudo[offsetKey] = containerKey == "startContainer" ? 0 : length - 1; 
     3207                return; 
     3208            } 
     3209            element = parent; 
     3210            parent = element.parentNode; 
     3211            childNodes = parent.childNodes; 
     3212            length = childNodes.length; 
     3213            for (offset = 0; offset < length; offset++) { 
     3214                if (element == childNodes[offset]) { 
     3215                    pseudo[containerKey] = parent; 
     3216                    pseudo[offsetKey] = offset; 
     3217                    return; 
     3218                } 
    30813219            } 
    30823220        } 
     
    30873225    }; 
    30883226    TracWysiwyg.prototype.getNativeSelectionRange = function() { 
    3089         var range = this.contentDocument.selection.createRange(); 
    3090         if (range && range.item) { 
    3091             range = range.item(0); 
    3092         } 
    3093         return range; 
     3227        return this.contentDocument.selection.createRange(); 
    30943228    }; 
    30953229    TracWysiwyg.prototype.getSelectionText = function() { 
    30963230        var range = this.getNativeSelectionRange(); 
    3097         return range ? range.text : null; 
     3231        if (range) { 
     3232            return range.item ? range.item(0).innerText : range.text; 
     3233        } 
     3234        return null; 
    30983235    }; 
    30993236    TracWysiwyg.prototype.getSelectionHTML = function() { 
    31003237        var range = this.getNativeSelectionRange(); 
    3101         return range ? range.htmlText : null; 
     3238        if (range) { 
     3239            return range.item ? range.item(0).innerHTML : range.htmlText; 
     3240        } 
     3241        return null; 
    31023242    }; 
    31033243    TracWysiwyg.prototype.getSelectionFragment = function() { 
     
    31793319    TracWysiwyg.prototype.insertHTML = function(html) { 
    31803320        var range = this.contentDocument.selection.createRange(); 
    3181         range.pasteHTML(html); 
     3321        if (/^\s+$/.exec(html)) { 
     3322            range.text = html; 
     3323        } 
     3324        else { 
     3325            range.pasteHTML(html.replace(/\t/g, "&#9;")); 
     3326        } 
    31823327    }; 
    31833328}