Changeset 4353


Ignore:
Timestamp:
Sep 27, 2008, 6:53:17 PM (16 years ago)
Author:
Jun Omae
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.
Location:
tracwysiwygplugin
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • 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}
Note: See TracChangeset for help on using the changeset viewer.