test: id value escaping for html and jquery selector

by Laurens Maneschijn

HTML

<div class="info">
  <h1>How do I select an element by an ID that has characters used in CSS notation?</h1>
  
  Problem description (and a possible solution, but solution seems incomplete):<br>
  <a target="_blank" href="https://learn.jquery.com/using-jquery-core/faq/how-do-i-select-an-element-by-an-id-that-has-characters-used-in-css-notation/">
    learn.jquery.com : How do I select an element by an ID that has characters used in CSS notation?
  </a>
</div>

<div class="tests">
	<h2>Tests</h2>

	<div id="a_b_c_d_e_f_g_h_i_j_k">
		1: safe id.<br>
	</div>

	<div id="a b.c#d>e+f&g[h]i:j€k">
	  2: id with lots of jquery selector breaking characters in it.<br>
	</div>

	<div id="a b.c#d&gt;e+f&amp;g[h]i:j€k">
		3: as id 2, but html escaped (&gt; and &amp;).<br>
	</div>

	<div id="a b.c#d>e+f&g[h]i:j_k">
		4: as id 2, without high characters (euro sign).<br>
	</div>
</div>



<div class="info">
  Links explaining used regex patterns:<br>
  <ul>
    <li><a href="https://regex101.com/r/9NIwhU/1">replace regex in getJquerySelectorSafeId1()</a></li>
    <li><a href="https://regex101.com/r/zS5h0I/1">replace regex in getJquerySelectorSafeId2()</a></li>
  </ul>
  
  <hr>
  Also see console logs for jQuery selector errormessages.
</div>

CSS

div{
	margin:3px;
	padding:3px;
	border-radius:3px;
	border: 1px solid #ccc;
}

.mark{
	display:inline-block;
}

div { background:#f0f0f0; }
div > div { background:#e8e8e8; }
div > div > div { background:#e0e0e0; }

div.info{
	margin-top:20px;
	margin-bottom:20px;
}

ul,li{margin:0px;}

h1,h2,h3,h4,h5,h6{
	margin:2px 0;
	padding:0;
	font-size:inherit;
}

JavaScript

function getJquerySelectorSafeId1(id){
  // jquery example solution:
  // from https://learn.jquery.com/using-jquery-core/faq/how-do-i-select-an-element-by-an-id-that-has-characters-used-in-css-notation/
  return (''+id).replace( /(:|\.|\[|\]|,|=|@)/g, "\\$1" );
}

function getJquerySelectorSafeId2(id){
  // own solution, seems more complete and seems to work for lots of funky characters:
  return (''+id).replace( /([ #>&+:.,=@[\]])/g, "\\$1" );
}


////////////////////
// run tests :
////////////////////

// test several different (unescaped) ids:
tryid('a_b_c_d_e_f_g_h_i_j_k', 'test id1'); // no magic chars here, should always work (control group).
tryid('a b.c#d>e+f&g[h]i:j€k', 'test id2'); // lots of magic chars; extreme testcase
tryid('a b.c#d>e+f&g[h]i:j_k', 'test id3');

// test several different id-escaping methods:
function tryid(id, id_description){
	try_id_sel_append(id, '#' + id, id_description + ' - noescape');
	try_id_sel_append(id, '#' + getJquerySelectorSafeId1(id), id_description + ' - escape1');
	try_id_sel_append(id, '#' + getJquerySelectorSafeId2(id), id_description + ' - escape2');
}

// run test and show results:
function try_id_sel_append(id, sel, description){
	var $sel;
	try{
//		console.log(id, sel, append);
		console.table([{id:id, selector:sel, description:description}]); // table has clearer output
		// select element with jquery, and if it worked, append a description to show which worked:
		$sel = $(sel);
		$sel.append( $('<div class="mark">').text(description) );
//		console.log($sel);
	}
	catch(e){
	  console.log(e);
	}
}