Menu

Firefox 3 breaks TAB-indent

2008-07-06
2013-04-24
  • Vebjørn Berg

    Vebjørn Berg - 2008-07-06

    Has anyone figured out a fix or workaround for this?
    With the release of Firefox 3, tab-indenting no longer works :/

     
    • matt-editme

      matt-editme - 2008-08-06

      Vebjorn,

      I'm using Firefox 3 and the tabs are working. It may be something else in your installation?

      Matt

       
      • Vebjørn Berg

        Vebjørn Berg - 2008-08-07

        Hi Matt!

        No i'm pretty darn sure it's a bug, and it's even present in the demo over at http://codepress.sourceforge.net/index.php . So far I'm encountering it on Firefox 3.0, Firefox 3.0.1 /Windows XP, Ubuntu 8.04.

        What setup are you on that has a working TAB-indent then?

         
    • Clancy Hood

      Clancy Hood - 2008-08-14

      Yup, it sure is a bug, though it was at NOFIX for a while: https://bugzilla.mozilla.org/show_bug.cgi?id=426690

      Matt, I'm amazed your works, yes what setup are you using?  I have Mac OS Tiger, Fedora 8, Windows XP, all with FF3, and no tabs in codepress.

      The bug summary is that it was an accessibility issue, and Mozilla decided to change the default behaviour for tabs to switch to the next page element and allow developers of inline editors to alter the behaviour, rather than relying on them to build in accessibility features (such as escape key gets you out of editor, or whatever).  It's been re-opened however since lots of feathers have been ruffled, no idea about what they're going to do though.

      I'm a major fan of codepress, but this is making my CMS somewhat unusable :( I *hate* indenting with spaces, and I usually forget anyway, hit tab and end up typing in nothing... so now I ssh in and use nano instead, which gives you some idea of how annoying it is.

      So we need a key listener on the parent window, to pass the TAB event through to the codepress window (right?).  I tried passing ctrl+s events back to the parent for saving documents and gave up after a couple of hours (my JS isn't too good when there's more than one window), so don't think I'm qualified, though I'll have a go at this in a minute... meantime, if anyone comes up with a fix, please do paste it in here, alternatively email me and I'll stick it up on a blog somewhere and put a link in at bugzilla - clancyhood[at]gmail

      Regards all :)

       
      • Franchie

        Franchie - 2008-08-14

        Hello,

        When I was still working with Codepress (I since started writing my own, as I needed more flexibility), I came up with a semi-solution for this problem. It was actually to fix the behaviour in IE, but it also works in Firefox 3.

        The idea was that since the basic Codepress package had a few useful functions missing, I created an 'extend_codepress' function that adds the functions without modifying Codepress itself, so that updates could be done easily.

        Within this 'extend_codepress' function, I had the TAB correction, and so I cut out the meaningful bits to present here. I hope I have not cut out anything important! One other thing, in order for things to work in IE also, I use selection objects. However, under IE, these are lost as soon as the editor looses focus. To get around this, and since all functions were to be called from a menu outside the editor, I used the mouseout event. If your code uses keyboard shortcuts as well, you should investigate whether the mouseout event has to be called manually before...

        So, enough words, here is the code, I hope it can be useful for someone!

        var global_ie_selection;        // IE hack, as it tends to loose focus!

        function extend_codepress(self)
        {
            // IE HACK...
            if(!window.selection && self.contentWindow.document.selection) {
                self.onmouseout = function(){global_ie_selection = self.contentWindow.document.selection.createRange();};
            }

            self.contentWindow.document.onkeydown = global_keyhandler;
            document.onkeydown = global_keyhandler;
           
            self.insertText = function(txt) {
                if(!self.contentWindow.document.selection) {
                    self.contentWindow.document.execCommand("inserthtml", null, txt);
                    self.focus();
                    self.editor.syntaxHighlight('code_insertion');
                }
                else {    // for IE ...
                    if(!global_ie_selection) global_ie_selection = self.contentWindow.document.selection.createRange();
                    self.focus();
                    txt = txt.replace(/\n/gi,'<P>');
                    txt = txt.replace(/<BR>/gi,'<P>');
                    // I forget the reason why spaces are necessary in IE... try maybe with a standard tab?
                    txt = txt.replace(/\t/gi,'&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;');
                    global_ie_selection.pasteHTML(txt);
                    global_ie_selection.select();
                    self.editor.syntaxHighlight('code_insertion');
                    self.onmouseout();
                }
            }
        }

        function global_keyhandler(evt)
        {
            evt = evt || window.event;
            var charCode = evt.keyCode;
            var fromChar = String.fromCharCode(charCode);
           
            if(fromChar == '\t') {
                if(evt.preventDefault) evt.preventDefault();        // Gecko and Others
                evt.returnValue = false;                            // IE
                /*Codepress_editor_handle*/.insertCode('\t');
                return false;
            }
           
            // Add other shortcuts here!
            return true;
        }

        /* SO in order to use, you would need to call extend_codepress( [handle of the editor] )
        You also need to replace all instances of "Codepress_editor_handle" and "Editor" to that handle*/

        Hope this helps!
        F.

         
        • Clancy Hood

          Clancy Hood - 2008-08-14

          Wow!  Thanks Franchie, I will certainly try this out.  You're a star x

           
    • FERLET Patrice

      FERLET Patrice - 2008-08-19

      Here what i did on gecko.js, replace keyHandler function by mine:

          // treat key bindings

          keyHandler : function(evt) {

              keyCode = evt.keyCode;

              charCode = evt.charCode;

              fromChar = String.fromCharCode(charCode);
             
              if(! (evt.ctrlKey || evt.metaKey || evt.shiftKey) && keyCode == 9) {
                  if(evt.preventDefault) evt.preventDefault(); // Gecko and Others
                  evt.returnValue = false; // IE
                  var code = '';
                  code = window.getSelection().getRangeAt(0).toString();
                  CodePress.insertCode('\t'+code);
                  CodePress.snippets(evt);                   
              }

              else if((evt.ctrlKey || evt.metaKey) && evt.shiftKey && charCode!=90)  { // shortcuts = ctrl||appleKey+shift+key!=z(undo)

                  CodePress.shortcuts(charCode?charCode:keyCode);

              }

              else if( (completeEndingChars.indexOf('|'+fromChar+'|')!= -1 || completeChars.indexOf('|'+fromChar+'|')!=-1) && CodePress.autocomplete) { // auto complete

                  if(!CodePress.completeEnding(fromChar))

                       CodePress.complete(fromChar);

              }

              else if(chars.indexOf('|'+charCode+'|')!=-1||keyCode==13) { // syntax highlighting

                  top.setTimeout(function(){CodePress.syntaxHighlight('generic');},100);

              }

              else if(keyCode==9 || evt.tabKey) {  // snippets activation (tab)

                  CodePress.snippets(evt);
                  evt.preventDefault();

              }

              else if(keyCode==46||keyCode==8) { // save to history when delete or backspace pressed

                   CodePress.actions.history[CodePress.actions.next()] = editor.innerHTML;

              }

              else if((charCode==122||charCode==121||charCode==90) && evt.ctrlKey) { // undo and redo

                  (charCode==121||evt.shiftKey) ? CodePress.actions.redo() :  CodePress.actions.undo();

                  evt.preventDefault();

              }

              else if(charCode==118 && evt.ctrlKey)  { // handle paste

                   top.setTimeout(function(){CodePress.syntaxHighlight('generic');},100);

              }

              else if(charCode==99 && evt.ctrlKey)  { // handle cut

                   //alert(window.getSelection().getRangeAt(0).toString().replace(/\t/g,'FFF'));

              }

          },

       
    • FERLET Patrice

      FERLET Patrice - 2008-08-19

      Or maybe, try this:
      It makes indent and outdent. This let Firefox to autoindent lines too.

      keyHandler : function(evt) {

              keyCode = evt.keyCode;

              charCode = evt.charCode;

              fromChar = String.fromCharCode(charCode);
             
              if(! (evt.ctrlKey || evt.metaKey) && keyCode == 9) {
                  if(evt.preventDefault) evt.preventDefault(); // Gecko and Others 
                  evt.returnValue = false; // IE 
                  window.document.execCommand((evt.shiftKey ? "outdent" : "indent"),false,false);
              } 

              if((evt.ctrlKey || evt.metaKey) && evt.shiftKey && charCode!=90)  { // shortcuts = ctrl||appleKey+shift+key!=z(undo)

                  CodePress.shortcuts(charCode?charCode:keyCode);

              }

              else if( (completeEndingChars.indexOf('|'+fromChar+'|')!= -1 || completeChars.indexOf('|'+fromChar+'|')!=-1) && CodePress.autocomplete) { // auto complete

                  if(!CodePress.completeEnding(fromChar))

                       CodePress.complete(fromChar);

              }

              else if(chars.indexOf('|'+charCode+'|')!=-1||keyCode==13) { // syntax highlighting

                  top.setTimeout(function(){CodePress.syntaxHighlight('generic');},100);

              }

              else if(keyCode==9 || evt.tabKey) {  // snippets activation (tab)

                  CodePress.snippets(evt);
                  evt.preventDefault();

              }

              else if(keyCode==46||keyCode==8 ||keyCode == 9) { // save to history when delete or backspace pressed

                   CodePress.actions.history[CodePress.actions.next()] = editor.innerHTML;

              }

              else if((charCode==122||charCode==121||charCode==90) && evt.ctrlKey) { // undo and redo

                  (charCode==121||evt.shiftKey) ? CodePress.actions.redo() :  CodePress.actions.undo();

                  evt.preventDefault();

              }

              else if(charCode==118 && evt.ctrlKey)  { // handle paste

                   top.setTimeout(function(){CodePress.syntaxHighlight('generic');},100);

              }

              else if(charCode==99 && evt.ctrlKey)  { // handle cut

                   //alert(window.getSelection().getRangeAt(0).toString().replace(/\t/g,'FFF'));

              }

          },

       
    • FERLET Patrice

      FERLET Patrice - 2008-08-19

      Finnaly... i did this:

      keyHandler : function(evt) {

              keyCode = evt.keyCode;

              charCode = evt.charCode;

              fromChar = String.fromCharCode(charCode);
             
              if(! (evt.ctrlKey || evt.metaKey) && keyCode == 9) {
                  if(evt.preventDefault) evt.preventDefault(); // Gecko and Others 
                  evt.returnValue = false; // IE 
                  var content = window.getSelection().getRangeAt(0);
                  var div = document.createElement('div');
                  div.appendChild(content.cloneContents());
                  if(!evt.shiftKey){
                      content = div.innerHTML.replace(/<br>/gi,'\n\t');       
                      content = content.replace(/\u2009/g,'');

                      content = content.replace(/<.*?>/g,'');

                      content = content.replace(/&lt;/g,'<');

                      content = content.replace(/&gt;/g,'>');

                      content = content.replace(/&amp;/gi,'&');               
                      CodePress.insertCode('\t'+content);
                  }
                  else {
                      content = div.innerHTML.replace(/<br>/gi,'\n');
                      content = content.replace(/^\t/g,'');
                      content = content.replace(/\n\t/g,'\n');
                      content = content.replace(/\u2009/g,'');

                      content = content.replace(/<.*?>/g,'');

                      content = content.replace(/&lt;/g,'<');

                      content = content.replace(/&gt;/g,'>');

                      content = content.replace(/&amp;/gi,'&');               
                      CodePress.insertCode(content);
                  }
                  CodePress.syntaxHighlight('generic');
              } 
      ....

       
    • brad laney

      brad laney - 2008-10-31

      If you are talking about making tabs work when you hit tab (i recently fixed this)

      It's very easy.

      open engines/gecko.js

      goto keyhandler : function

      goto else if(keyCode==9 || evt.tabKey) {  // snippets activation (tab)

      replace this if block with:

                  if (!CodePress.snippets(evt)) {
                      var range = window.getSelection().getRangeAt(0);
                      var newTextNode = document.createTextNode('\t');
                      range.insertNode(newTextNode);
                      range.setStartAfter(newTextNode)
                  }
                  evt.preventDefault(); // prevent the tab key from being added

      goto     snippets : function(evt) {

      first line of the function add
              var workWasDone = false;

      then add the second line that follows after the if statement, which is the first line here:
                  if(snippets[i].input == trigger) {
                      workWasDone = true;

      finally the last line of this function is:
              return workWasDone;

      Now when you hit tab, it will make a tab and everyone claps their hands.

       
    • Hayoun Laurent

      Hayoun Laurent - 2008-12-15

      Hi,

      your code is useful but need to be updated, because
      when you highlighnt multiple line TAB doesn't work and also shift + tab is not supported, is it possible to update the code for gecko ?

      thnak you for your great help !

       
    • Alf Nielsen

      Alf Nielsen - 2009-01-28

      well its actual the same as brad laney (2up By: brad laney (digitalpacman) - 2008-10-31 20:49)
      but I think is it a little easier:

      simply replace the snippets function with:

              var snippets = Language.snippets;   
              var trigger = this.getLastWord();
              var tab = true;
              for (var i=0; i<snippets.length; i++) {
                  if(snippets[i].input == trigger) {
                      tab = false;
                      var content = snippets[i].output.replace(/</g,'&lt;');
                      content = content.replace(/>/g,'&gt;');
                      if(content.indexOf('$0')<0) content += cc;
                      else content = content.replace(/\$0/,cc);
                      content = content.replace(/\n/g,'<br>');
                      var pattern = new RegExp(trigger+cc,'gi');
                      evt.preventDefault(); // prevent the tab key from being added
                      this.syntaxHighlight('snippets',pattern,content);
                  }
              }
              if(tab){
                  var range = window.getSelection().getRangeAt(0);
                  var newTextNode = document.createTextNode('\t');
                  range.insertNode(newTextNode);
                  range.setStartAfter(newTextNode)
                  evt.preventDefault(); // prevent the normal tab action
              }

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.