¿Cómo puedo escapar una cadena dentro del código JavaScript dentro de un controlador onClick?


Tal vez estoy pensando demasiado en esto, pero estoy teniendo un problema para averiguar qué escape usar en una cadena en algún código JavaScript dentro del controlador onClick de un enlace. Ejemplo:

<a href="#" onclick="SelectSurveyItem('<%itemid%>', '<%itemname%>'); return false;">Select</a>

El <%itemid%> y <%itemname%> son donde se produce la sustitución de plantilla. Mi problema es que el nombre del elemento puede contener cualquier carácter, incluyendo comillas simples y dobles. Actualmente, si contiene comillas simples rompe el código JavaScript.

Mi primer pensamiento fue utilizar el lenguaje de la plantilla función para JavaScript-escape el nombre del elemento, que simplemente escapa de las comillas. Eso no solucionará el caso de la cadena que contiene comillas dobles que rompe el HTML del enlace. ¿Cómo se aborda normalmente este problema? ¿Necesito HTML-escape todo el controlador onClick?

Si es así, eso se vería realmente extraño ya que la función de escape del lenguaje de plantillas para que también HTMLify los paréntesis, comillas y punto y coma...

Este enlace se genera para cada resultado en un página de resultados de búsqueda, por lo que crear un método separado dentro de una etiqueta JavaScript no es posible, porque tendría que generar uno por resultado.

Además, estoy usando un motor de plantillas que fue desarrollado en casa en la empresa para la que trabajo, por lo que las soluciones específicas de toolkit no me servirán de nada.

Author: Peter Mortensen, 2008-09-19

13 answers

En JavaScript puede codificar comillas simples como "\x27" y comillas dobles como "\x22". Por lo tanto, con este método puede, una vez que esté dentro de las comillas (dobles o simples) de un literal de cadena de JavaScript, usar \x27 \x22 con impunidad sin temor a que se "rompan" las comillas incrustadas de su cadena.

\ xXX es para caracteres Unicode , por lo que armado con este conocimiento puede crear una función robusta JSEncode para todos los caracteres que están fuera del lista blanca habitual.

Por ejemplo,

<a href="#" onclick="SelectSurveyItem('<% JSEncode(itemid) %>', '<% JSEncode(itemname) %>'); return false;">Select</a>
 77
Author: Duncan Smart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-04 17:21:30

Dependiendo del lenguaje del lado del servidor, puede usar uno de estos:

. NET 4.0

string result = System.Web.HttpUtility.JavaScriptStringEncode("jsString")

Java

import org.apache.commons.lang.StringEscapeUtils;
...

String result = StringEscapeUtils.escapeJavaScript(jsString);

Python

import json
result = json.dumps(jsString)

PHP

$result = strtr($jsString, array('\\' => '\\\\', "'" => "\\'", '"' => '\\"', 
                                 "\r" => '\\r', "\n" => '\\n' ));

Ruby on Rails

<%= escape_javascript(jsString) %>
 20
Author: Vitalii Fedorenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-23 03:15:57

Utilice tramos ocultos, uno para cada uno de los parámetros <%itemid%> y <%itemname%> y escriba sus valores dentro de ellos.

Por ejemplo, el intervalo para <%itemid%> se vería como <span id='itemid' style='display:none'><%itemid%></span> y en la función javascript SelectSurveyItem para recoger los argumentos de estos intervalos' innerHTML.

 10
Author: Shyam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-21 16:02:41

Intente evitar el uso de literales de cadena en su HTML y use JavaScript para enlazar eventos JavaScript.

También, evita 'href=#' a menos que realmente sepas lo que estás haciendo. Rompe tanta usabilidad para middleclickers compulsivos (abridor de pestañas).

<a id="tehbutton" href="somewhereToGoWithoutWorkingJavascript.com">Select</a>

Mi biblioteca JavaScript de elección simplemente resulta ser jQuery:

<script type="text/javascript">//<!-- <![CDATA[
jQuery(function($){
   $("#tehbutton").click(function(){
        SelectSurveyItem('<%itemid%>', '<%itemname%>');
        return false;
   });
});
//]]>--></script>

Si resulta que está renderizando una lista de enlaces como esa, es posible que desee hacer esto:

<a id="link_1" href="foo">Bar</a>
<a id="link_2" href="foo2">Baz</a>

<script type="text/javascript">
   jQuery(function($){
        var l = [[1,'Bar'],[2,'Baz']];
        $(l).each(function(k,v){
           $("#link_" + v[0] ).click(function(){
                SelectSurveyItem(v[0],v[1]);
                return false;
           });
        });
   });
 </script>
 9
Author: Kent Fredric,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-04 17:14:53

Si va a un atributo HTML, necesitará codificar HTML (como mínimo: > para &gt; < para &lt y " para &quot;), y escape comillas simples (con una barra invertida) para que no interfieran con las citas de javascript.

La mejor manera de hacerlo es con su sistema de plantillas (extendiéndolo, si es necesario), pero simplemente podría hacer un par de funciones de escape/codificación y envolverlas ambas alrededor de cualquier dato que vaya allí.

Y sí, es perfectamente válido (correcto, incluso) para HTML-escape de todo el contenido de sus atributos HTML, incluso si contienen javascript.

 8
Author: Dan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 22:26:43

Otra solución interesante podría ser hacer esto:

<a href="#" itemid="<%itemid%>" itemname="<%itemname%>" onclick="SelectSurveyItem(this.itemid, this.itemname); return false;">Select</a>

Entonces puede usar una codificación HTML estándar en ambas variables, sin tener que preocuparse por la complicación adicional de las citas de javascript.

Sí, esto crea HTML que es estrictamente inválido. Sin embargo, es una técnica válida, y todos los navegadores modernos la soportan.

Si fuera mío, probablemente iría con mi primera sugerencia, y me aseguraría de que los valores estén codificados en HTML y tengan las comillas simples escaparon.

 3
Author: Dan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 22:41:17

Declare funciones separadas en la sección

e invoque las de su método onClick. Si tiene muchos, podría usar un esquema de nomenclatura que los numera, o pasar un entero en sus onClicks y tener una instrucción big fat switch en la función.
 1
Author: moonshadow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 22:45:38

También me he enfrentado a este problema. Hice un script para convertir comillas simples en comillas dobles escapadas que no romperán el HTML.

function noQuote(text)
{
    var newtext = "";
    for (var i = 0; i < text.length; i++) {
        if (text[i] == "'") {
            newtext += "\"";
        }
        else {
            newtext += text[i];
        }
    }
    return newtext;
}
 1
Author: Starbuck Johnson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-04 17:17:54

Utilice la biblioteca Microsoft Anti-XSS que incluye una codificación JavaScript.

 1
Author: blowdart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-04 17:21:55

Primero, sería más simple si el controlador onclick se configurara de esta manera:

<a id="someLinkId"href="#">Select</a>
<script type="text/javascript">
  document.getElementById("someLinkId").onClick = 
   function() {
      SelectSurveyItem('<%itemid%>', '<%itemname%>'); return false;
    };

</script>

Entonces itemid y itemname necesitan ser escapados para JavaScript (es decir, " se convierte en \", etc.).

Si está utilizando Java en el lado del servidor, puede echar un vistazo a la clase StringEscapeUtils de jakarta common-lang. De lo contrario, no debería tomar demasiado tiempo escribir su propio método 'escapeJavascript'.

 1
Author: Alexandre Victoor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-04 17:23:11

Es la respuesta aquí que no puede escapar comillas usando JavaScript y que necesita comenzar con cadenas escapadas.

Por lo tanto. No hay forma de que JavaScript sea capaz de manejar la cadena 'Marge dijo" Yo miraría que era "a Peter' y necesita que sus datos sean limpiados antes de ofrecerlos al script?

 0
Author: Steve Perks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-19 11:35:07

Cualquier buen motor de plantillas que valga la pena tendrá una función de "comillas de escape". El nuestro (también local, donde trabajo) también tiene una función para escapar de las comillas para javascript. En ambos casos, la variable de plantilla se añade simplemente con _esc o _js_esc, dependiendo de la que desee. Nunca debe enviar contenido generado por el usuario a un navegador que no se haya escapado, en mi humilde opinión.

 0
Author: livingtech,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-19 15:20:05

Me enfrenté al mismo problema, y lo resolví de una manera complicada. Primero haga variables globales, v1, v2 y v3. Y en el onclick, envíe un indicador, 1, 2 o 3 y en la función verifique 1, 2, 3 para poner el v1, v2 y v3 como:

onclick="myfun(1)"
onclick="myfun(2)"
onclick="myfun(3)"

function myfun(var)
{
    if (var ==1)
        alert(v1);

    if (var ==2)
        alert(v2);

    if (var ==3)
        alert(v3);
}
 0
Author: AhmedGamal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-04 17:17:01