Figure 8-3.Comment preview with escaped HTMLString#escapeHTMLfinds characters with special meaning in HTML—specifically angle "Never, never pour salt in your eyes.".escapeHTML; //-> "Nev
Trang 1Figure 8-2.The code doesn’t sanitize user input.
From a server-side perspective, failing to sanitize user input is a huge security risk From a client-side perspective, it’s also a monkey wrench in your page design If we’re not
allowing HTML in blog comments, then we’ve got to escape the input so that every
char-acter is treated as a literal value (see Figure 8-3):
function updateLivePreview() {
var commentText = $('comment_text').value.escapeHTML();
$('live_preview').update(commentText);
}
Trang 2Figure 8-3.Comment preview with escaped HTML
String#escapeHTMLfinds characters with special meaning in HTML—specifically angle
"Never, <em>never</em> pour salt in your eyes.".escapeHTML();
//-> "Never, <em>never</em> pour salt in your eyes."
"Never, <em>never</em> pour salt in your eyes.".unescapeHTML();
//-> "Never, <em>never</em> pour salt in your eyes."
So that’s one approach we can take Another would be to ignore anything that looks
like HTML, rather than display it literally:
"Never, <em>never</em> pour salt in your eyes.".stripTags();
//-> "Never, never pour salt in your eyes."
Trang 3In fact, this solution better captures the commenter’s original intent.
String#stripTagsremoves all HTML from a string, leaving behind only plain text (see Figure 8-4)
■ Caution Never, ever use client-side sanitization as a replacement for server-side sanitization Client-side
sanitization is trivial to bypass and gives you a false sense of security Instead, decide how the server will handle unusual input, and then write client-side code to mirror that behavior Live comment preview is a UI
feature—not a security measure.
Figure 8-4.HTML no longer has an effect on the page.
The camelize, underscore, and dasherize Methods
These string-formatting methods spring from identical methods in the popular Rails framework They’re used to convert between different methods of word delimiting I’ll let the code explain itself:
"lorem-ipsum-dolor".underscore(); //-> "lorem_ipsum_dolor"
"lorem_ipsum_dolor".dasherize(); //-> "lorem-ipsum-dolor"
"lorem-ipsum-dolor".camelize(); //-> "loremIpsumDolor"
Trang 4You can see that underscoreconverts hyphens to underscores, dasherizeconverts
underscores to hyphens (yes, hyphens, even though the method calls them dashes!), and
camelizeremoves hyphens while capitalizing the letters that follow (otherwise known as
camel case)
names in either their hyphenated or their camelized variants:
$('foo').setStyle({ paddingBottom: '10px' });
$('foo').setStyle({ 'padding-bottom': '10px' });
Element#setStylemakes this possible by calling String#camelizeto ensure that all
property names are in camel case
The capitalize and truncate Methods
will convert the first letter of a string to uppercase and all other letters to lowercase:
"never".capitalize(); //-> "Never";
"NEVER".capitalize(); //-> "Never";
"Never".capitalize(); //-> "Never";
String#truncateis quite interesting It will return the first n characters of a string,
along with an ellipsis to indicate the truncation:
var warning = "Never, never pour salt in your eyes."
var truncation = warning.truncate(15); //-> "Never, never "
truncation.length; //-> 15
The first argument, naturally, indicates how long you’d like the resulting string to be
The optional second argument lets you specify a custom truncation, if you’re not a fan of
of the returned string
var otherTruncation = warning.truncate(20, ">>>>>");
//-> "Never, never po>>>>>"
Trang 5The include, startsWith, endsWith, empty, and blank Methods
Last of all are five methods that test the content of strings All five return a Boolean—
trueor false
String#includetests for a simple substring match String#startsWithand
String#endsWithdo the same, but test whether the anchored substring exists at the beginning or the end of the string, respectively:
var warning = "Never, never pour salt in your eyes."
warning.include("salt"); //-> true
warning.startsWith("salt"); //-> false
warning.startsWith("N"); //-> true
warning.startsWith("n"); //-> false
warning.endsWith("your eyes.") //-> true
All three of these methods are case sensitive
String#emptyand String#blanktake no arguments—they simply test if the string is empty (has a length of 0) or blank (contains only whitespace):
" ".blank(); //-> true
" ".empty(); //-> false
"".empty(); //-> true
"".blank(); //-> true
All empty strings are blank, but not all blank strings are empty
The Template Class and String Interpolation
Think of your favorite programming language right now (If your favorite language is JavaScript, you’re an anomaly Think of your second favorite.) The language you’re think-ing of certainly has some handy way of mixthink-ing variables into existthink-ing strthink-ings
PHP and Ruby, for instance, give us variable interpolation:
// PHP:
echo "Touchdown scored by ${position} ${first_name} ${last_name}!";
// Ruby:
puts "Touchdown scored by #{position} #{first_name} #{last_name}!";
Trang 6In both these languages, we can mark certain parts of a string to be replaced by
vari-ables We notify the language’s interpreter by using a special pattern in the string
JavaScript doesn’t have variable interpolation, but since when has that stopped us?
We can fake it
Using the Template Class
var t = new Template("The quick brown #{first} jumps over the lazy #{second}.");
special syntax we use inside the string—it’s identical to Ruby’s
Now we can use this template over and over again, passing different values for
t.evaluate({ first: "fox", second: "dog" });
//-> "The quick brown fox jumps over the lazy dog."
t.evaluate({ first: "yak", second: "emu" });
//-> "The quick brown yak jumps over the lazy emu."
t.evaluate({ first: "tree", second: "human" });
//-> "The quick brown tree jumps over the lazy human."
Ignore the increasing improbabilities of these statements Instead, note that
Template#evaluatetakes one argument, an Object, with properties corresponding to the
names we used in the original string Note also that we need only create the template
once—but we can use it over and over to generate strings that conform to the same
pattern
Since an array is just a special kind of object with numeric property names, you can
define a template that uses numbered replacements:
var t = new Template("The quick brown #{0} jumps over the lazy #{1}.");
t.evaluate(["bandicoot", "hyena"]);
//-> "The quick brown bandicoot jumps over the lazy hyena."
Of course, sometimes you won’t need to interpolate more than once So there’s also
String#interpolate:
"The quick brown #{first} jumps over the lazy #{second}."
.interpolate({ first: "ocelot", second: "ibex" });
//-> "The quick brown ocelot jumps over the lazy ibex."