2008-09-26 24 views
43

¿Es posible resaltar texto dentro de un área de texto usando javascript? ¿Cambiando el fondo de solo una parte del área de texto o haciendo una parte del texto seleccionado?Resaltar texto dentro de un área de texto

+0

Estoy implementando la parte resaltada de texto encontrado de una función de búsqueda y reemplazo. – alumb

+1

[Este enlace] (http://www.sitepoint.com/life-autocomplete-textboxes/) parece que podría comenzar. –

Respuesta

15

Prueba este trozo de código que he escrito esta mañana, se pondrán de relieve un conjunto definido de palabras:

<html> 
    <head> 
     <title></title> 
     <!-- Load jQuery --> 
     <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script> 
     <!-- The javascript xontaining the plugin and the code to init the plugin --> 
     <script type="text/javascript"> 
      $(function() { 
       // let's init the plugin, that we called "highlight". 
       // We will highlight the words "hello" and "world", 
       // and set the input area to a widht and height of 500 and 250 respectively. 
       $("#container").highlight({ 
        words: ["hello","world"], 
        width: 500, 
        height: 250 
       }); 
      }); 

      // the plugin that would do the trick 
      (function($){ 
       $.fn.extend({ 
        highlight: function() { 
         // the main class 
         var pluginClass = function() {}; 
         // init the class 
         // Bootloader 
         pluginClass.prototype.__init = function (element) { 
          try { 
           this.element = element; 
          } catch (err) { 
           this.error(err); 
          } 
         }; 
         // centralized error handler 
         pluginClass.prototype.error = function (e) { 
          // manage error and exceptions here 
          //console.info("error!",e); 
         }; 
         // Centralized routing function 
         pluginClass.prototype.execute = function (fn, options) { 
          try { 
           options = $.extend({},options); 
           if (typeof(this[fn]) == "function") { 
            var output = this[fn].apply(this, [options]); 
           } else { 
            this.error("undefined_function"); 
           } 
          } catch (err) { 
           this.error(err); 
          } 
         }; 
         // ********************** 
         // Plugin Class starts here 
         // ********************** 
         // init the component 
         pluginClass.prototype.init = function (options) { 
          try { 
           // the element's reference ($("#container")) is stored into "this.element" 
           var scope     = this; 
           this.options    = options; 

           // just find the different elements we'll need 
           this.highlighterContainer = this.element.find('#highlighterContainer'); 
           this.inputContainer   = this.element.find('#inputContainer'); 
           this.textarea    = this.inputContainer.find('textarea'); 
           this.highlighter   = this.highlighterContainer.find('#highlighter'); 

           // apply the css 
           this.element.css('position','relative'); 

           // place both the highlight container and the textarea container 
           // on the same coordonate to superpose them. 
           this.highlighterContainer.css({ 
            'position':   'absolute', 
            'left':    '0', 
            'top':    '0', 
            'border':   '1px dashed #ff0000', 
            'width':   this.options.width, 
            'height':   this.options.height, 
            'cursor':   'text' 
           }); 
           this.inputContainer.css({ 
            'position':   'absolute', 
            'left':    '0', 
            'top':    '0', 
            'border':   '1px solid #000000' 
           }); 
           // now let's make sure the highlit div and the textarea will superpose, 
           // by applying the same font size and stuffs. 
           // the highlighter must have a white text so it will be invisible 
           this.highlighter.css({ 

            'padding':   '7px', 
            'color':   '#eeeeee', 
            'background-color': '#ffffff', 
            'margin':   '0px', 
            'font-size':  '11px', 
            'font-family':  '"lucida grande",tahoma,verdana,arial,sans-serif' 
           }); 
           // the textarea must have a transparent background so we can see the highlight div behind it 
           this.textarea.css({ 
            'background-color': 'transparent', 
            'padding':   '5px', 
            'margin':   '0px', 
            'font-size':  '11px', 
            'width':   this.options.width, 
            'height':   this.options.height, 
            'font-family':  '"lucida grande",tahoma,verdana,arial,sans-serif' 
           }); 

           // apply the hooks 
           this.highlighterContainer.bind('click', function() { 
            scope.textarea.focus(); 
           }); 
           this.textarea.bind('keyup', function() { 
            // when we type in the textarea, 
            // we want the text to be processed and re-injected into the div behind it. 
            scope.applyText($(this).val()); 
           }); 
          } catch (err) { 
           this.error(err); 
          } 
          return true; 
         }; 
         pluginClass.prototype.applyText = function (text) { 
          try { 
           var scope     = this; 

           // parse the text: 
           // replace all the line braks by <br/>, and all the double spaces by the html version &nbsp; 
           text = this.replaceAll(text,'\n','<br/>'); 
           text = this.replaceAll(text,' ','&nbsp;&nbsp;'); 

           // replace the words by a highlighted version of the words 
           for (var i=0;i<this.options.words.length;i++) { 
            text = this.replaceAll(text,this.options.words[i],'<span style="background-color: #D8DFEA;">'+this.options.words[i]+'</span>'); 
           } 

           // re-inject the processed text into the div 
           this.highlighter.html(text); 

          } catch (err) { 
           this.error(err); 
          } 
          return true; 
         }; 
         // "replace all" function 
         pluginClass.prototype.replaceAll = function(txt, replace, with_this) { 
          return txt.replace(new RegExp(replace, 'g'),with_this); 
         } 

         // don't worry about this part, it's just the required code for the plugin to hadle the methods and stuffs. Not relevant here. 
         //********************** 
         // process 
         var fn; 
         var options; 
         if (arguments.length == 0) { 
          fn = "init"; 
          options = {}; 
         } else if (arguments.length == 1 && typeof(arguments[0]) == 'object') { 
          fn = "init"; 
          options = $.extend({},arguments[0]); 
         } else { 
          fn = arguments[0]; 
          options = $.extend({},arguments[1]); 
         } 

         $.each(this, function(idx, item) { 
          // if the component is not yet existing, create it. 
          if ($(item).data('highlightPlugin') == null) { 
           $(item).data('highlightPlugin', new pluginClass()); 
           $(item).data('highlightPlugin').__init($(item)); 
          } 
          $(item).data('highlightPlugin').execute(fn, options); 
         }); 
         return this; 
        } 
       }); 

      })(jQuery); 


     </script> 
    </head> 
    <body> 

     <div id="container"> 
      <div id="highlighterContainer"> 
       <div id="highlighter"> 

       </div> 
      </div> 
      <div id="inputContainer"> 
       <textarea cols="30" rows="10"> 

       </textarea> 
      </div> 
     </div> 

    </body> 
</html> 

Esto fue escrito para otro post (http://facebook.stackoverflow.com/questions/7497824/how-to-highlight-friends-name-in-facebook-status-update-box-textarea/7597420 # 7597420), pero parece ser lo que está buscando.

+0

Cool. ¿Hay alguna manera de que esa secuencia de comandos pueda ser editada en esa cadena en lugar de solo palabras individuales podría ser resaltada? Noté que cuando quiero que se destaque una frase como "New York Yankees", ¿no funciona? ¿Algunas ideas? – Lance

0

Versión mejorada desde arriba, también trabaja con expresiones regulares y más campos TextArea:

<html> 
    <head> 
     <title></title> 
    <!-- Load jQuery --> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script> 
    <!-- The javascript xontaining the plugin and the code to init the plugin --> 
    <script type="text/javascript"> 
     $(function() { 
      // let's init the plugin, that we called "highlight". 
      // We will highlight the words "hello" and "world", 
      // and set the input area to a widht and height of 500 and 250 respectively. 
      $("#container0").highlight({ 
       words: [["hello","hello"],["world","world"],["(\\[b])(.+?)(\\[/b])","$1$2$3"]], 
       width: 500, 
       height: 125, 
     count:0 
      }); 
      $("#container1").highlight({ 
       words: [["hello","hello"],["world","world"],["(\\[b])(.+?)(\\[/b])","$1$2$3"]], 
       width: 500, 
       height: 125, 
     count: 1 
      }); 
     }); 

     // the plugin that would do the trick 
     (function($){ 
      $.fn.extend({ 
       highlight: function() { 
        // the main class 
        var pluginClass = function() {}; 
        // init the class 
        // Bootloader 
        pluginClass.prototype.__init = function (element) { 
         try { 
          this.element = element; 
         } catch (err) { 
          this.error(err); 
         } 
        }; 
        // centralized error handler 
        pluginClass.prototype.error = function (e) { 
         // manage error and exceptions here 
         //console.info("error!",e); 
        }; 
        // Centralized routing function 
        pluginClass.prototype.execute = function (fn, options) { 
         try { 
          options = $.extend({},options); 
          if (typeof(this[fn]) == "function") { 
           var output = this[fn].apply(this, [options]); 
          } else { 
           this.error("undefined_function"); 
          } 
         } catch (err) { 
          this.error(err); 
         } 
        }; 
        // ********************** 
        // Plugin Class starts here 
        // ********************** 
        // init the component 
        pluginClass.prototype.init = function (options) { 
         try { 
          // the element's reference ($("#container")) is stored into "this.element" 
          var scope     = this; 
          this.options    = options; 

          // just find the different elements we'll need 

          this.highlighterContainer = this.element.find('#highlighterContainer'+this.options.count); 
          this.inputContainer   = this.element.find('#inputContainer'+this.options.count); 
          this.textarea    = this.inputContainer.find('textarea'); 
          this.highlighter   = this.highlighterContainer.find('#highlighter'+this.options.count); 

          // apply the css 
          this.element.css({'position':'relative', 
       'overflow':'auto', 
       'background':'none repeat scroll 0 0 #FFFFFF', 
       'height':this.options.height+2, 
       'width':this.options.width+19, 
       'border':'1px solid' 
       }); 

          // place both the highlight container and the textarea container 
          // on the same coordonate to superpose them. 
          this.highlighterContainer.css({ 
           'position':   'absolute', 
           'left':    '0', 
           'top':    '0', 
           'border':   '1px dashed #ff0000', 
           'width':   this.options.width, 
           'height':   this.options.height, 
           'cursor':   'text', 
       'z-index':  '1' 
          }); 
          this.inputContainer.css({ 
           'position':   'absolute', 
           'left':    '0', 
           'top':    '0', 
           'border':   '0px solid #000000', 
       'z-index':  '2', 
       'background': 'none repeat scroll 0 0 transparent' 
          }); 
          // now let's make sure the highlit div and the textarea will superpose, 
          // by applying the same font size and stuffs. 
          // the highlighter must have a white text so it will be invisible 
      var isWebKit = navigator.userAgent.indexOf("WebKit") > -1, 
      isOpera = navigator.userAgent.indexOf("Opera") > -1, 
isIE /*@cc_on = true @*/, 
isIE6 = isIE && !window.XMLHttpRequest; // Despite the variable name, this means if IE lower than v7 

if (isIE || isOpera){ 
var padding = '6px 5px'; 
} 
else { 
var padding = '5px 6px'; 
} 
          this.highlighter.css({ 
           'padding':  padding, 
           'color':   '#eeeeee', 
           'background-color': '#ffffff', 
           'margin':   '0px', 
           'font-size':  '11px' , 
           'line-height':  '12px' , 
           'font-family':  '"lucida grande",tahoma,verdana,arial,sans-serif' 
          }); 

          // the textarea must have a transparent background so we can see the highlight div behind it 
          this.textarea.css({ 
           'background-color': 'transparent', 
           'padding':   '5px', 
           'margin':   '0px', 
           'width':   this.options.width, 
           'height':   this.options.height, 
           'font-size':  '11px', 
           'line-height':  '12px' , 
           'font-family':  '"lucida grande",tahoma,verdana,arial,sans-serif', 
       'overflow':  'hidden', 
           'border':   '0px solid #000000' 
          }); 

          // apply the hooks 
          this.highlighterContainer.bind('click', function() { 
           scope.textarea.focus(); 
          }); 
          this.textarea.bind('keyup', function() { 
           // when we type in the textarea, 
           // we want the text to be processed and re-injected into the div behind it. 
           scope.applyText($(this).val()); 
          }); 

      scope.applyText(this.textarea.val()); 

         } catch (err) { 
      this.error(err) 
         } 
         return true; 
        }; 
        pluginClass.prototype.applyText = function (text) { 
         try { 
          var scope     = this; 

          // parse the text: 
          // replace all the line braks by <br/>, and all the double spaces by the html version &nbsp; 
          text = this.replaceAll(text,'\n','<br/>'); 
          text = this.replaceAll(text,' ','&nbsp;&nbsp;'); 
          text = this.replaceAll(text,' ','&nbsp;'); 

          // replace the words by a highlighted version of the words 
          for (var i=0;i<this.options.words.length;i++) { 
           text = this.replaceAll(text,this.options.words[i][0],'<span style="background-color: #D8DFEA;">'+this.options.words[i][1]+'</span>'); 
           //text = this.replaceAll(text,'(\\[b])(.+?)(\\[/b])','<span style="font-weight:bold;background-color: #D8DFEA;">$1$2$3</span>'); 
          } 

          // re-inject the processed text into the div 
          this.highlighter.html(text); 
      if (this.highlighter[0].clientHeight > this.options.height) { 
       // document.getElementById("highlighter0") 
       this.textarea[0].style.height=this.highlighter[0].clientHeight +19+"px"; 
      } 
      else { 
       this.textarea[0].style.height=this.options.height; 
      } 

         } catch (err) { 
          this.error(err); 
         } 
         return true; 
        }; 
        // "replace all" function 
        pluginClass.prototype.replaceAll = function(txt, replace, with_this) { 
         return txt.replace(new RegExp(replace, 'g'),with_this); 
        } 

        // don't worry about this part, it's just the required code for the plugin to hadle the methods and stuffs. Not relevant here. 
        //********************** 
        // process 
        var fn; 
        var options; 
        if (arguments.length == 0) { 
         fn = "init"; 
         options = {}; 
        } else if (arguments.length == 1 && typeof(arguments[0]) == 'object') { 
         fn = "init"; 
         options = $.extend({},arguments[0]); 
        } else { 
         fn = arguments[0]; 
         options = $.extend({},arguments[1]); 
        } 

        $.each(this, function(idx, item) { 
         // if the component is not yet existing, create it. 
         if ($(item).data('highlightPlugin') == null) { 
          $(item).data('highlightPlugin', new pluginClass()); 
          $(item).data('highlightPlugin').__init($(item)); 
         } 
         $(item).data('highlightPlugin').execute(fn, options); 
        }); 
        return this; 
       } 
      }); 

     })(jQuery); 


    </script> 
</head> 
<body> 

    <div id="container0"> 
     <div id="highlighterContainer0"> 
      <div id="highlighter0"></div> 
     </div> 
     <div id="inputContainer0"> 
      <textarea id="text1" cols="30" rows="15">hello world</textarea> 
     </div> 
    </div> 
<h1> haus </h1> 
    <div id="container1"> 
     <div id="highlighterContainer1"> 
      <div id="highlighter1"></div> 
     </div> 
     <div id="inputContainer1"> 
      <textarea cols="30" rows="15">hipp hipp 
hurra, 
[b]ich hab es jetzt![/b]</textarea> 
     </div> 
    </div> 

</body> 

+0

Sería mejor tener esto en un violín o algo parecido. –

3

Fácil guión que escribí para esto: Jsfiddle

OPCIONES:

  1. Contador de caracteres opcional.
  2. Resalta varios patrones con diferentes colores.
  3. Regex.
  4. Recoge las coincidencias con otros contenedores.
  5. Estilo sencillo: fuentes de color y cara, fondos, radio de borde y altura de línea.
  6. Ctrl + Shift para cambio de dirección.

    //include function like in the fiddle! 
    
    //CREATE ELEMENT: 
    
    create_bind_textarea_highlight({ 
        eleId:"wrap_all_highlighter", 
        width:400, 
        height:110, 
        padding:5, 
        background:'white', 
        backgroundControls:'#585858', 
        radius:5, 
        fontFamilly:'Arial', 
        fontSize:13, 
        lineHeight:18, 
        counterlettres:true, 
        counterFont:'red', 
        matchpatterns:[["(#[0-9A-Za-z]{0,})","$1"],["(@[0-9A-Za-z]{0,})","$1"]], 
        hightlightsColor:['#00d2ff','#FFBF00'], 
        objectsCopy:["copy_hashes","copy_at"] 
        //PRESS Ctrl + SHIFT for direction swip! 
        }); 
    
    //HTML EXAMPLE: 
    <div id="wrap_all_highlighter" placer='1'></div> 
    <div id='copy_hashes'></div><!--Optional--> 
    <div id='copy_at'></div><!--Optional--> 
    

divertirse!

+0

esto es bueno, pero ¿qué ocurre si el usuario ingresa el nombre y el apellido? – user1851420

Cuestiones relacionadas