Pregunta

Estoy usando JavaScript para tirar de un valor de un campo oculto y lo mostrará en un cuadro de texto.El valor del campo oculto está codificado.

Por ejemplo,

<input id='hiddenId' type='hidden' value='chalk &amp; cheese' />

se retiró en

<input type='text' value='chalk &amp; cheese' />

a través de algunos de jQuery para obtener el valor del campo oculto (es en este punto que voy a perder la codificación):

$('#hiddenId').attr('value')

El problema es que cuando he leído chalk &amp; cheese desde el campo oculto, JavaScript parece perder la codificación.Yo no quiero que el valor de la chalk & cheese.Quiero que el literal amp; para ser retenidos.

Hay una biblioteca de JavaScript o jQuery, método que va a HTML-codificar una cadena?

¿Fue útil?

Solución

EDITAR: esta respuesta fue publicada hace mucho tiempo, y la función htmlDecode introdujo una vulnerabilidad XSS. Se ha modificado cambiando el elemento temporal de un div a un textarea reduciendo la posibilidad de XSS. Pero hoy en día, le animo a utilizar la API DOMParser como se sugiere en otra respuesta .


Uso estas funciones:

function htmlEncode(value){
  // Create a in-memory element, set its inner text (which is automatically encoded)
  // Then grab the encoded contents back out. The element never exists on the DOM.
  return $('<textarea/>').text(value).html();
}

function htmlDecode(value){
  return $('<textarea/>').html(value).text();
}

Básicamente se crea un elemento div en la memoria, pero nunca se agrega al documento.

En la función htmlEncode configuro el innerText del elemento y recupero el innerHTML codificado; en la función <=> configuro el valor <=> del elemento y se recupera el <=>.

Verifique un ejemplo en ejecución aquí .

Otros consejos

El truco jQuery no codifica comillas y en IE eliminará su espacio en blanco.

Basado en la etiqueta de plantilla escape en Django, que supongo que ya está muy utilizada / probada, hice esta función que hace lo que se necesita.

Podría decirse que es más simple (y posiblemente más rápido) que cualquiera de las soluciones para el problema de eliminación de espacios en blanco, y codifica comillas, lo cual es esencial si va a utilizar el resultado dentro de un valor de atributo, por ejemplo.

function htmlEscape(str) {
    return str
        .replace(/&/g, '&amp;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;');
}

// I needed the opposite function today, so adding here too:
function htmlUnescape(str){
    return str
        .replace(/&quot;/g, '"')
        .replace(/&#39;/g, "'")
        .replace(/&lt;/g, '<')
        .replace(/&gt;/g, '>')
        .replace(/&amp;/g, '&');
}

Actualización 2013-06-17:
En la búsqueda del escape más rápido, he encontrado esta implementación de un método replaceAll:
http://dumpsite.com/forum/index.php?topic=4 .msg29 # msg29
(también se hace referencia aquí: Método más rápido para reemplazar todas las instancias de un carácter en una cadena )
Algunos resultados de rendimiento aquí:
http://jsperf.com/htmlencoderegex/25

Da una cadena de resultados idéntica a las cadenas replace integradas arriba. ¡Me encantaría que alguien pudiera explicar por qué es más rápido!

Actualización 04/03/2015:
Acabo de notar que AngularJS está utilizando exactamente el método anterior:
https://github.com/angular /angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js#L435

Agregan un par de refinamientos: parecen estar manejando un oscuro problema de Unicode además de convertir todos los caracteres no alfanuméricos en entidades. Tenía la impresión de que esto último no era necesario siempre y cuando tenga un juego de caracteres UTF8 especificado para su documento.

Notaré que (4 años después) Django todavía no hace ninguna de estas cosas, así que no estoy seguro de cuán importantes son:
https://github.com/django/django/ blob / 1.8b1 / django / utils / html.py # L44

Actualización 2016-04-06:
También es posible que desee escapar de la barra diagonal /. Esto no es necesario para la correcta codificación HTML, sin embargo se recomienda por OWASP como medida de seguridad anti-XSS. (gracias a @JNF por sugerir esto en los comentarios)

        .replace(/\//g, '&#x2F;');

Aquí no es la versión de jQuery que es considerablemente más rápido que el de jQuery .html() versión y el .replace() versión.Esto conserva todos los espacios en blanco, pero como la versión de jQuery, no manejar citas.

function htmlEncode( html ) {
    return document.createElement( 'a' ).appendChild( 
        document.createTextNode( html ) ).parentNode.innerHTML;
};

Velocidad: http://jsperf.com/htmlencoderegex/17

speed test

Demo: jsFiddle

Salida:

output

Secuencia de comandos:

function htmlEncode( html ) {
    return document.createElement( 'a' ).appendChild( 
        document.createTextNode( html ) ).parentNode.innerHTML;
};

function htmlDecode( html ) {
    var a = document.createElement( 'a' ); a.innerHTML = html;
    return a.textContent;
};

document.getElementById( 'text' ).value = htmlEncode( document.getElementById( 'hidden' ).value );

//sanity check
var html = '<div>   &amp; hello</div>';
document.getElementById( 'same' ).textContent = 
      'html === htmlDecode( htmlEncode( html ) ): ' 
    + ( html === htmlDecode( htmlEncode( html ) ) );

HTML:

<input id="hidden" type="hidden" value="chalk    &amp; cheese" />
<input id="text" value="" />
<div id="same"></div>

Sé que esta es antigua, pero quería publicar una variación de la respuesta aceptada que funcionará en IE sin eliminar líneas:

function multiLineHtmlEncode(value) {
    var lines = value.split(/\r\n|\r|\n/);
    for (var i = 0; i < lines.length; i++) {
        lines[i] = htmlEncode(lines[i]);
    }
    return lines.join('\r\n');
}

function htmlEncode(value) {
    return $('<div/>').text(value).html();
} 

El subrayado proporciona _.escape() y _.unescape() métodos que hacen esto.

> _.unescape( "chalk &amp; cheese" );
  "chalk & cheese"

> _.escape( "chalk & cheese" );
  "chalk &amp; cheese"

Buena respuesta. Tenga en cuenta que si el valor para codificar es undefined o null con jQuery 1.4.2, puede obtener errores como:

jQuery("<div/>").text(value).html is not a function

O

Uncaught TypeError: Object has no method 'html'

La solución es modificar la función para verificar un valor real:

function htmlEncode(value){ 
    if (value) {
        return jQuery('<div/>').text(value).html(); 
    } else {
        return '';
    }
}

Para aquellos que prefieren JavaScript simple, este es el método que he usado con éxito:

function escapeHTML (str)
{
    var div = document.createElement('div');
    var text = document.createTextNode(str);
    div.appendChild(text);
    return div.innerHTML;
}

FWIW, la codificación no se está perdiendo. La codificación es utilizada por el analizador de marcado (navegador) durante la carga de la página. Una vez que la fuente se lee y analiza y el navegador tiene el DOM cargado en la memoria, la codificación se analiza en lo que representa. Entonces, cuando su JS se ejecuta para leer algo en la memoria, el carácter que obtiene es lo que representa la codificación.

Puedo estar operando estrictamente en semántica aquí, pero quería que entendiera el propósito de la codificación. La palabra & Quot; perdido & Quot; hace que parezca que algo no funciona como debería.

Prototype lo tiene incorporado en el Clase de cadena . Entonces, si está usando / planea usar Prototype, hace algo como:

'<div class="article">This is an article</div>'.escapeHTML();
// -> "&lt;div class="article"&gt;This is an article&lt;/div&gt;"

Más rápido sin Jquery. Puede codificar todos los caracteres de su cadena:

function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}

O simplemente apunta a los personajes principales de los que preocuparte (& amp ;, inebreaks, < ;, > ;, " y ') como:

function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}

test.value=encode('Encode HTML entities!\n\n"Safe" escape <script id=\'\'> & useful in <pre> tags!');

testing.innerHTML=test.value;

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<textarea id=test rows="9" cols="55"></textarea>

<div id="testing">www.WHAK.com</div>

Aquí hay una solución javascript simple. Extiende el objeto String con un método & Quot; HTMLEncode & Quot; que se puede usar en un objeto sin parámetro o con un parámetro.

String.prototype.HTMLEncode = function(str) {
  var result = "";
  var str = (arguments.length===1) ? str : this;
  for(var i=0; i<str.length; i++) {
     var chrcode = str.charCodeAt(i);
     result+=(chrcode>128) ? "&#"+chrcode+";" : str.substr(i,1)
   }
   return result;
}
// TEST
console.log("stetaewteaw æø".HTMLEncode());
console.log("stetaewteaw æø".HTMLEncode("æåøåæå"))

He realizado un gist " Método HTMLEncode para javascript " .

Basado en angular's sanitize ... (sintaxis del módulo es6)

// ref: https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js
const SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
const NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g;

const decodeElem = document.createElement('pre');


/**
 * Decodes html encoded text, so that the actual string may
 * be used.
 * @param value
 * @returns {string} decoded text
 */
export function decode(value) {
  if (!value) return '';
  decodeElem.innerHTML = value.replace(/</g, '&lt;');
  return decodeElem.textContent;
}


/**
 * Encodes all potentially dangerous characters, so that the
 * resulting string can be safely inserted into attribute or
 * element text.
 * @param value
 * @returns {string} encoded text
 */
export function encode(value) {
  if (value === null || value === undefined) return '';
  return String(value).
    replace(/&/g, '&amp;').
    replace(SURROGATE_PAIR_REGEXP, value => {
      var hi = value.charCodeAt(0);
      var low = value.charCodeAt(1);
      return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
    }).
    replace(NON_ALPHANUMERIC_REGEXP, value => {
      return '&#' + value.charCodeAt(0) + ';';
    }).
    replace(/</g, '&lt;').
    replace(/>/g, '&gt;');
}

export default {encode,decode};

afaik no hay métodos directos de codificación / decodificación HTML en javascript.

Sin embargo, lo que puede hacer es usar JS para crear un elemento arbitrario, establecer su texto interno y luego leerlo con innerHTML.

digamos, con jQuery esto debería funcionar:

var helper = $('chalk & cheese').hide().appendTo('body');
var htmled = helper.html();
helper.remove();

o algo por el estilo

No debería tener que escapar / codificar valores para transferirlos de un campo de entrada a otro.

<form>
 <input id="button" type="button" value="Click me">
 <input type="hidden" id="hiddenId" name="hiddenId" value="I like cheese">
 <input type="text" id="output" name="output">
</form>
<script>
    $(document).ready(function(e) {
        $('#button').click(function(e) {
            $('#output').val($('#hiddenId').val());
        });
    });
</script>

JS no va a insertar HTML sin formato ni nada; solo le dice al DOM que establezca la propiedad value (o atributo; no estoy seguro). De cualquier manera, el DOM maneja cualquier problema de codificación por usted. A menos que esté haciendo algo extraño como usar document.write o eval, la codificación HTML será efectivamente transparente.

Si está hablando de generar un nuevo cuadro de texto para guardar el resultado ... sigue siendo tan fácil. Simplemente pase la parte estática del HTML a jQuery, y luego configure el resto de las propiedades / atributos en el objeto que le devuelve.

$box = $('<input type="text" name="whatever">').val($('#hiddenId').val());

Tuve un problema similar y lo solucioné usando la función encodeURIComponent de JavaScript ( documentación )

Por ejemplo, en su caso si usa:

<input id='hiddenId' type='hidden' value='chalk & cheese' />

y

encodeURIComponent($('#hiddenId').attr('value'))

obtendrá chalk%20%26%20cheese. Incluso los espacios se mantienen.

En mi caso, tuve que codificar una barra invertida y este código funciona perfectamente

encodeURIComponent('name/surname')

y obtuve name%2Fsurname

Mi función JS puro:

/**
 * HTML entities encode
 *
 * @param {string} str Input text
 * @return {string} Filtered text
 */
function htmlencode (str){

  var div = document.createElement('div');
  div.appendChild(document.createTextNode(str));
  return div.innerHTML;
}
  

JavaScript HTML Entities Encode & amp; Decodificar

Si quieres usar jQuery. Encontré esto:

http://www.jquerysdk.com/api/jQuery.htmlspecialchars

(parte del complemento jquery.string ofrecido por jQuery SDK)

Creo que el problema con Prototype es que extiende los objetos base en JavaScript y será incompatible con cualquier jQuery que haya utilizado. Por supuesto, si ya está utilizando Prototype y no jQuery, no será un problema.

EDITAR: También existe esto, que es un puerto de las utilidades de cadena de Prototype para jQuery:

http://stilldesigning.com/dotstring/

var htmlEnDeCode = (function() {
    var charToEntityRegex,
        entityToCharRegex,
        charToEntity,
        entityToChar;

    function resetCharacterEntities() {
        charToEntity = {};
        entityToChar = {};
        // add the default set
        addCharacterEntities({
            '&amp;'     :   '&',
            '&gt;'      :   '>',
            '&lt;'      :   '<',
            '&quot;'    :   '"',
            '&#39;'     :   "'"
        });
    }

    function addCharacterEntities(newEntities) {
        var charKeys = [],
            entityKeys = [],
            key, echar;
        for (key in newEntities) {
            echar = newEntities[key];
            entityToChar[key] = echar;
            charToEntity[echar] = key;
            charKeys.push(echar);
            entityKeys.push(key);
        }
        charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g');
        entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
    }

    function htmlEncode(value){
        var htmlEncodeReplaceFn = function(match, capture) {
            return charToEntity[capture];
        };

        return (!value) ? value : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn);
    }

    function htmlDecode(value) {
        var htmlDecodeReplaceFn = function(match, capture) {
            return (capture in entityToChar) ? entityToChar[capture] : String.fromCharCode(parseInt(capture.substr(2), 10));
        };

        return (!value) ? value : String(value).replace(entityToCharRegex, htmlDecodeReplaceFn);
    }

    resetCharacterEntities();

    return {
        htmlEncode: htmlEncode,
        htmlDecode: htmlDecode
    };
})();

Esto es del código fuente ExtJS.

<script>
String.prototype.htmlEncode = function () {
    return String(this)
        .replace(/&/g, '&amp;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;');

}

var aString = '<script>alert("I hack your site")</script>';
console.log(aString.htmlEncode());
</script>

Saldrá: &lt;script&gt;alert(&quot;I hack your site&quot;)&lt;/script&gt;

.htmlEncode () estará accesible en todas las cadenas una vez definidas.

HtmlEncodes el valor dado

  var htmlEncodeContainer = $('<div />');
  function htmlEncode(value) {
    if (value) {
      return htmlEncodeContainer.text(value).html();
    } else {
      return '';
    }
  }

Me encontré con algunos problemas con la barra invertida en mi cadena Dominio \ Usuario.

Agregué esto a los otros escapes de la respuesta de Anentropic

.replace(/\\/g, '&#92;')

Que encontré aquí: ¿Cómo escapar de la barra diagonal inversa en JavaScript?

Aquí hay un poco que emula la función Server.HTMLEncode de la ASP de Microsoft, escrita en JavaScript puro:

function htmlEncode(s) {
  var ntable = {
    "&": "amp",
    "<": "lt",
    ">": "gt",
    "\"": "quot"
  };
  s = s.replace(/[&<>"]/g, function(ch) {
    return "&" + ntable[ch] + ";";
  })
  s = s.replace(/[^ -\x7e]/g, function(ch) {
    return "&#" + ch.charCodeAt(0).toString() + ";";
  });
  return s;
}

El resultado no codifica apóstrofes, pero codifica los otros especiales HTML y cualquier carácter fuera del rango 0x20-0x7e.

Elegir lo que escapeHTML() está haciendo en prototype.js

Agregar este script lo ayuda a escapar de HTML:

String.prototype.escapeHTML = function() { 
    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
}

ahora puede llamar al método escapeHTML en cadenas en su secuencia de comandos, como:

var escapedString = "<h1>this is HTML</h1>".escapeHTML();
// gives: "&lt;h1&gt;this is HTML&lt;/h1&gt;"

Espero que ayude a cualquiera que busque una solución simple sin tener que incluir todo el prototype.js

Utilizando algunas de las otras respuestas aquí, hice una versión que reemplaza todos los caracteres pertinentes en una pasada, independientemente del número de caracteres codificados distintos (solo una llamada a replace()), por lo que será más rápido para cadenas más grandes.

No depende de la API DOM para existir o de otras bibliotecas.

window.encodeHTML = (function() {
    function escapeRegex(s) {
        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
    }
    var encodings = {
        '&'  : '&amp;',
        '"'  : '&quot;',
        '\'' : '&#39;',
        '<'  : '&lt;',
        '>'  : '&gt;',
        '\\' : '&#x2F;'
    };
    function encode(what) { return encodings[what]; };
    var specialChars = new RegExp('[' +
        escapeRegex(Object.keys(encodings).join('')) +
    ']', 'g');

    return function(text) { return text.replace(specialChars, encode); };
})();

Después de ejecutar eso una vez, ahora puede llamar

encodeHTML('<>&"\'')

Para obtener &lt;&gt;&amp;&quot;&#39;

function encodeHTML(str) {
    return document.createElement("a").appendChild( 
        document.createTextNode(str)).parentNode.innerHTML;
};

function decodeHTML(str) {
    var element = document.createElement("a"); 
    element.innerHTML = str;
    return element.textContent;
};
var str = "<"
var enc = encodeHTML(str);
var dec = decodeHTML(enc);
console.log("str: " + str, "\nenc: " + enc, "\ndec: " + dec);

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top