Reputation: 1408
I came across this pen at codePen, and found a bug. If you type in the following chars in the searchbox:
), (, [, +, \, *, ?
I get the following error (I entered each char separately):
I think the problem is at the regular expression part. Line 19:
var rgx = new RegExp(this.value, "i");
Why does this happen and how can I fix it?
document.addEventListener("DOMContentLoaded", function() {
"use strict"
var style = "" + "<style>" + ".filter .hidden {" + "opacity: 0;" + "}" +
".filter > * {" + "position: absolute;" +
"transition: .5s ease-in-out;" + "}" + "</style>";
document.head.insertAdjacentHTML("beforeend", style);
var list = document.querySelectorAll(".filter > *");
var h = list[0].offsetHeight,
arr = [],
i = -1,
l = list.length;
var anim = "transform" in document.body.style ? "transform" : "webkitTransform";
while (++i < l) {
arr.push(list[i].textContent.trim());
list[i].style[anim] = "translateY(" + i * h + "px)";
}
document.querySelector("input.filter").addEventListener("input", function() {
var rgx = new RegExp(this.value, "i");
arr.forEach(function(el, idx) {
if (rgx.test(el)) list[idx].classList.remove("hidden");
else list[idx].classList.add("hidden");
var i = -1;
var p = 0;
while (++i < l) {
if (list[i].className != "hidden")
list[i].style[anim] = "translateY(" + p++ * h + "px)";
}
})
})
})
@import url(https://fonts.googleapis.com/css?family=Titillium+Web);
html {
height: 100%;
}
body {
width: 100%;
height: 100%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
margin: 0;
font: 14px'Titillium Web', sans-serif;
letter-spacing: 2px;
background: -webkit-linear-gradient(320deg, #543958 0%, #a06060 25%, #bea27b 50%, #9ca898 75%, #506d8d 100%) no-repeat center center fixed;
background: linear-gradient(130deg, #543958 0%, #a06060 25%, #bea27b 50%, #9ca898 75%, #506d8d 100%) no-repeat center center fixed;
}
section {
-webkit-align-self: top;
-ms-flex-item-align: top;
align-self: top;
margin: 150px 0;
display: block;
position: relative;
width: 380px;
max-height: 550px;
color: rgba(244, 230, 254, 0.7);
background: rgba(199, 131, 252, 0.05);
border-top: 15px solid rgba(0, 0, 0, 0.15);
border-bottom: 40px solid rgba(0, 0, 0, 0.06);
-webkit-filter: drop-shadow(26px 26px 20px rgba(0, 0, 0, 0.5));
filter: drop-shadow(26px 26px 20px rgba(0, 0, 0, 0.5));
box-shadow: -4vh -6vh 16vh -6vh rgba(0, 0, 0, 0.2), -4vh 6vh 16vh -6vh rgba(0, 0, 0, 0.15);
}
section header {
padding: 1em 1.4em;
background: rgba(0, 0, 0, 0.12);
margin: 0 auto 0 auto;
}
section header h4 {
height: 3rem;
margin: 0 0 1rem 0;
padding: 0;
line-height: 1.1rem;
text-align: center;
border-radius: 3px;
font-size: 1.1rem;
}
section header h4 span {
padding: 1.2rem;
}
section header h4 span.c {
padding: .5rem;
background: rgba(0, 0, 0, 0.045);
border-bottom: 2px solid rgba(233, 205, 254, 0.8);
}
section header input[type="search"] {
margin: 0 .5rem;
padding: .5rem;
width: 95%;
color: rgba(244, 230, 254, 0.8);
background: transparent;
border: none;
border-bottom: 1px solid rgba(210, 158, 250, 0.5);
font-size: 1.15rem;
-webkit-transition: translateX 6s ease-in;
transition: translateX 6s ease-in;
}
section header input[type="search"]:focus {
outline: none;
border: 1px solid rgba(210, 158, 250, 0.5);
}
section header input[type="search"]:focus::-webkit-input-placeholder {
-webkit-transform: translateX(70%);
transform: translateX(70%);
opacity: 0;
}
section header input[type="search"]:focus::-webkit-input-placeholder:-moz-placeholder {
-webkit-transform: translateX(70%);
transform: translateX(70%);
opacity: 0;
}
section header input[type="search"]:focus::-webkit-input-placeholder::-moz-placeholder {
-webkit-transform: translateX(70%);
transform: translateX(70%);
opacity: 0;
}
section header input[type="search"]:focus::-webkit-input-placeholder:-ms-input-placeholder {
-webkit-transform: translateX(70%);
transform: translateX(70%);
opacity: 0;
}
section header input[type="search"]:focus::-webkit-input-placeholder::-ms-input-placeholder {
-webkit-transform: translateX(70%);
transform: translateX(70%);
opacity: 0;
}
section header input[type="search"]::-webkit-input-placeholder {
color: rgba(233, 205, 254, 0.8);
-webkit-transition: ease-in 0.3s;
transition: ease-in 0.3s;
-webkit-transform-origin: 0 50%;
transform-origin: 0 50%;
}
section header input[type="search"]:-moz-placeholder {
color: rgba(233, 205, 254, 0.8);
-webkit-transition: ease-in 0.3s;
transition: ease-in 0.3s;
transform-origin: 0 50%;
}
section header input[type="search"]::-moz-placeholder {
color: rgba(233, 205, 254, 0.8);
-webkit-transition: ease-in 0.3s;
transition: ease-in 0.3s;
transform-origin: 0 50%;
}
section header input[type="search"]:-ms-input-placeholder {
color: rgba(233, 205, 254, 0.8);
-webkit-transition: ease-in 0.3s;
transition: ease-in 0.3s;
transform-origin: 0 50%;
}
section header input[type="search"]::-ms-input-placeholder {
color: rgba(233, 205, 254, 0.8);
-webkit-transition: ease-in 0.3s;
transition: ease-in 0.3s;
transform-origin: 0 50%;
}
section .filter {
padding: 1rem 0;
}
section .filter li {
width: 100%;
padding: 1rem 0;
line-height: 1.5rem;
-webkit-filter: drop-shadow(26px 26px 20px rgba(0, 0, 0, 0.7));
filter: drop-shadow(26px 26px 20px rgba(0, 0, 0, 0.7));
list-style-type: none;
text-align: left;
}
section .filter li span {
font-size: 1.15rem;
padding: 1.8rem;
}
section .filter li:nth-child(odd) {
background: rgba(255, 255, 255, 0.03);
margin: 0;
}
<section>
<header>
<h4>
<span>Log</span>
<span>Favorites</span>
<span class ='c'>Contacts</span>
</h4>
<input type='search' placeholder="🔍 Search" autofocus class="filter">
</header>
<ul class="filter">
<li><span class='img'>👦</span><span class='name'>John</span> <span class='ph'>609-579-1254</span>
</li>
<li><span class='img'>👧</span><span class='name'>Diane</span> <span class='ph'>908-240-2297</span>
</li>
<li><span class='img'>👦</span><span class='name'>Mike</span> <span class='ph'>303-539-1425</span>
</li>
<li><span class='img'>👧</span><span class='name'>Mary</span> <span class='ph'>424-308-9976</span>
</li>
<li><span class='img'>👦</span><span class='name'>Adam</span> <span class='ph'>509-998-0025</span>
</li>
<li><span class='img'>👦</span><span class='name'>Billy</span> <span class='ph'>609-898-3325</span>
</li>
</ul>
</section>
Upvotes: 2
Views: 2059
Reputation:
This might be a good way to replace all the metachars to make them literal's.
text_escaped = text.replace(/([.^$|*+?()\[\]{}\\-])/g, "\\$1");
Update
After looking at your codepen link, I saw that you were not instantiation
the regex objcect correctly.
The parameters are as follows: RegExp( string, flags )
I believe you were using this wrong.
Yours var rgx = new RegExp(this.value, text_escaped);
Should have been var rgx = new RegExp(text_escaped);
Here are a couple of useful links about JavaScript regex:
Regex Reference's
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions http://www.w3schools.com/jsref/jsref_obj_regexp.asp
From there it shows how you can define your own function to escape metacharacters.
Escaping user input to be treated as a literal string within a regular expression can be accomplished by a simple replacement:
function escapeRegExp(string){
return string.replace(/([.*+?^${}()|[\]\\])/g, "\\$1"); // $1 means capture group 1
}
Then a usage example is something like:
var text_to_find = "<[SBG]>";
var findRx = new RegExp( escapeRegExp( text_to_find ) );
// Use findRx here ..
Upvotes: 2
Reputation: 444
The answer to this question requires a familiarity with Regular Expressions. From http://www.regular-expressions.info:
A regular expression (regex or regexp for short) is a special text string for describing a search pattern. You can think of regular expressions as wildcards on steroids. You are probably familiar with wildcard notations such as *.txt to find all text files in a file manager. The regex equivalent is .*\.txt$.
Regular expressions are put together using a variety of special characters, all of which have different meanings. The characters that, as you discovered, cause the search box to break are considered special characters in regular expressions. For example, (
and )
are used to indicate "groups" of characters within the regular expression.
To briefly answer the question of "how to fix it": the easy way would be to add a \
in front of any special characters in this.value
. \
is a special character which causes the character that immediately follows it to be considered as a "non-special" character.
e.g.
var escapedValue = this.value.replace(")", "\\)");
escapedValue = escapedValue.replace("(", "\\(");
escapedValue = escapedValue.replace("[", "\\[");
escapedValue = escapedValue.replace("+", "\\+");
escapedValue = escapedValue.replace("\\", "\\\\)");
escapedValue = escapedValue.replace("*", "\\*");
escapedValue = escapedValue.replace("?", "\\?");
var rgx = new RegExp(escapedValue, "i");
Note that this code snippet won't completely fix the problem (the list of special characters isn't exhaustive), and it's not a very elegant solution, but it illustrates the general concept.
Upvotes: 1