Related
I have the following code in Ruby. I want to convert this code into JavaScript. What is the equivalent code in JS?
text = <<"HERE"
This
Is
A
Multiline
String
HERE
Update:
ECMAScript 6 (ES6) introduces a new type of literal, namely template literals. They have many features, variable interpolation among others, but most importantly for this question, they can be multiline.
A template literal is delimited by backticks:
var html = `
<div>
<span>Some HTML here</span>
</div>
`;
(Note: I'm not advocating to use HTML in strings)
Browser support is OK, but you can use transpilers to be more compatible.
Original ES5 answer:
Javascript doesn't have a here-document syntax. You can escape the literal newline, however, which comes close:
"foo \
bar"
ES6 Update:
As the first answer mentions, with ES6/Babel, you can now create multi-line strings simply by using backticks:
const htmlString = `Say hello to
multi-line
strings!`;
Interpolating variables is a popular new feature that comes with back-tick delimited strings:
const htmlString = `${user.name} liked your post about strings`;
This just transpiles down to concatenation:
user.name + ' liked your post about strings'
Original ES5 answer:
Google's JavaScript style guide recommends to use string concatenation instead of escaping newlines:
Do not do this:
var myString = 'A rather long string of English text, an error message \
actually that just keeps going and going -- an error \
message to make the Energizer bunny blush (right through \
those Schwarzenegger shades)! Where was I? Oh yes, \
you\'ve got an error and all the extraneous whitespace is \
just gravy. Have a nice day.';
The whitespace at the beginning of each line can't be safely stripped at compile time; whitespace after the slash will result in tricky errors; and while most script engines support this, it is not part of ECMAScript.
Use string concatenation instead:
var myString = 'A rather long string of English text, an error message ' +
'actually that just keeps going and going -- an error ' +
'message to make the Energizer bunny blush (right through ' +
'those Schwarzenegger shades)! Where was I? Oh yes, ' +
'you\'ve got an error and all the extraneous whitespace is ' +
'just gravy. Have a nice day.';
the pattern text = <<"HERE" This Is A Multiline String HERE is not available in js (I remember using it much in my good old Perl days).
To keep oversight with complex or long multiline strings I sometimes use an array pattern:
var myString =
['<div id="someId">',
'some content<br />',
'someRefTxt',
'</div>'
].join('\n');
or the pattern anonymous already showed (escape newline), which can be an ugly block in your code:
var myString =
'<div id="someId"> \
some content<br /> \
someRefTxt \
</div>';
Here's another weird but working 'trick'1:
var myString = (function () {/*
<div id="someId">
some content<br />
someRefTxt
</div>
*/}).toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1];
external edit: jsfiddle
ES20xx supports spanning strings over multiple lines using template strings:
let str = `This is a text
with multiple lines.
Escapes are interpreted,
\n is a newline.`;
let str = String.raw`This is a text
with multiple lines.
Escapes are not interpreted,
\n is not a newline.`;
1 Note: this will be lost after minifying/obfuscating your code
You can have multiline strings in pure JavaScript.
This method is based on the serialization of functions, which is defined to be implementation-dependent. It does work in the most browsers (see below), but there's no guarantee that it will still work in the future, so do not rely on it.
Using the following function:
function hereDoc(f) {
return f.toString().
replace(/^[^\/]+\/\*!?/, '').
replace(/\*\/[^\/]+$/, '');
}
You can have here-documents like this:
var tennysonQuote = hereDoc(function() {/*!
Theirs not to make reply,
Theirs not to reason why,
Theirs but to do and die
*/});
The method has successfully been tested in the following browsers (not mentioned = not tested):
IE 4 - 10
Opera 9.50 - 12 (not in 9-)
Safari 4 - 6 (not in 3-)
Chrome 1 - 45
Firefox 17 - 21 (not in 16-)
Rekonq 0.7.0 - 0.8.0
Not supported in Konqueror 4.7.4
Be careful with your minifier, though. It tends to remove comments. For the YUI compressor, a comment starting with /*! (like the one I used) will be preserved.
I think a real solution would be to use CoffeeScript.
ES6 UPDATE: You could use backtick instead of creating a function with a comment and running toString on the comment. The regex would need to be updated to only strip spaces. You could also have a string prototype method for doing this:
let foo = `
bar loves cake
baz loves beer
beer loves people
`.removeIndentation()
Someone should write this .removeIndentation string method... ;)
You can do this...
var string = 'This is\n' +
'a multiline\n' +
'string';
I came up with this very jimmy rigged method of a multi lined string. Since converting a function into a string also returns any comments inside the function you can use the comments as your string using a multilined comment /**/. You just have to trim off the ends and you have your string.
var myString = function(){/*
This is some
awesome multi-lined
string using a comment
inside a function
returned as a string.
Enjoy the jimmy rigged code.
*/}.toString().slice(14,-3)
alert(myString)
I'm surprised I didn't see this, because it works everywhere I've tested it and is very useful for e.g. templates:
<script type="bogus" id="multi">
My
multiline
string
</script>
<script>
alert($('#multi').html());
</script>
Does anybody know of an environment where there is HTML but it doesn't work?
I solved this by outputting a div, making it hidden, and calling the div id by jQuery when I needed it.
e.g.
<div id="UniqueID" style="display:none;">
Strings
On
Multiple
Lines
Here
</div>
Then when I need to get the string, I just use the following jQuery:
$('#UniqueID').html();
Which returns my text on multiple lines. If I call
alert($('#UniqueID').html());
I get:
There are multiple ways to achieve this
1. Slash concatenation
var MultiLine= '1\
2\
3\
4\
5\
6\
7\
8\
9';
2. regular concatenation
var MultiLine = '1'
+'2'
+'3'
+'4'
+'5';
3. Array Join concatenation
var MultiLine = [
'1',
'2',
'3',
'4',
'5'
].join('');
Performance wise, Slash concatenation (first one) is the fastest.
Refer this test case for more details regarding the performance
Update:
With the ES2015, we can take advantage of its Template strings feature. With it, we just need to use back-ticks for creating multi line strings
Example:
`<h1>{{title}}</h1>
<h2>{{hero.name}} details!</h2>
<div><label>id: </label>{{hero.id}}</div>
<div><label>name: </label>{{hero.name}}</div>
`
Using script tags:
add a <script>...</script> block containing your multiline text into head tag;
get your multiline text as is... (watch out for text encoding: UTF-8, ASCII)
<script>
// pure javascript
var text = document.getElementById("mySoapMessage").innerHTML ;
// using JQuery's document ready for safety
$(document).ready(function() {
var text = $("#mySoapMessage").html();
});
</script>
<script id="mySoapMessage" type="text/plain">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="...">
<soapenv:Header/>
<soapenv:Body>
<typ:getConvocadosElement>
...
</typ:getConvocadosElement>
</soapenv:Body>
</soapenv:Envelope>
<!-- this comment will be present on your string -->
//uh-oh, javascript comments... SOAP request will fail
</script>
I like this syntax and indendation:
string = 'my long string...\n'
+ 'continue here\n'
+ 'and here.';
(but actually can't be considered as multiline string)
Downvoters: This code is supplied for information only.
This has been tested in Fx 19 and Chrome 24 on Mac
DEMO
var new_comment; /*<<<EOF
<li class="photobooth-comment">
<span class="username">
You:
</span>
<span class="comment-text">
$text
</span>
#<span class="comment-time">
2d
</span> ago
</li>
EOF*/
// note the script tag here is hardcoded as the FIRST tag
new_comment=document.currentScript.innerHTML.split("EOF")[1];
document.querySelector("ul").innerHTML=new_comment.replace('$text','This is a dynamically created text');
<ul></ul>
A simple way to print multiline strings in JavaScript is by using template literals(template strings) denoted by backticks (` `). you can also use variables inside a template string-like (` name is ${value} `)
You can also
const value = `multiline`
const text = `This is a
${value}
string in js`;
console.log(text);
There's this library that makes it beautiful:
https://github.com/sindresorhus/multiline
Before
var str = '' +
'<!doctype html>' +
'<html>' +
' <body>' +
' <h1>❤ unicorns</h1>' +
' </body>' +
'</html>' +
'';
After
var str = multiline(function(){/*
<!doctype html>
<html>
<body>
<h1>❤ unicorns</h1>
</body>
</html>
*/});
Found a lot of over engineered answers here.
The two best answers in my opinion were:
1:
let str = `Multiline string.
foo.
bar.`
which eventually logs:
Multiline string.
foo.
bar.
2:
let str = `Multiline string.
foo.
bar.`
That logs it correctly but it's ugly in the script file if str is nested inside functions / objects etc...:
Multiline string.
foo.
bar.
My really simple answer with regex which logs the str correctly:
let str = `Multiline string.
foo.
bar.`.replace(/\n +/g, '\n');
Please note that it is not the perfect solution but it works if you are sure that after the new line (\n) at least one space will come (+ means at least one occurrence). It also will work with * (zero or more).
You can be more explicit and use {n,} which means at least n occurrences.
The equivalent in javascript is:
var text = `
This
Is
A
Multiline
String
`;
Here's the specification. See browser support at the bottom of this page. Here are some examples too.
This works in IE, Safari, Chrome and Firefox:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<div class="crazy_idea" thorn_in_my_side='<table border="0">
<tr>
<td ><span class="mlayouttablecellsdynamic">PACKAGE price $65.00</span></td>
</tr>
</table>'></div>
<script type="text/javascript">
alert($(".crazy_idea").attr("thorn_in_my_side"));
</script>
to sum up, I have tried 2 approaches listed here in user javascript programming (Opera 11.01):
this one didn't work: Creating multiline strings in JavaScript
this worked fairly well, I have also figured out how to make it look good in Notepad++ source view: Creating multiline strings in JavaScript
So I recommend the working approach for Opera user JS users. Unlike what the author was saying:
It doesn't work on firefox or opera; only on IE, chrome and safari.
It DOES work in Opera 11. At least in user JS scripts. Too bad I can't comment on individual answers or upvote the answer, I'd do it immediately. If possible, someone with higher privileges please do it for me.
Exact
Ruby produce: "This\nIs\nA\nMultiline\nString\n" - below JS produce exact same string
text = `This
Is
A
Multiline
String
`
// TEST
console.log(JSON.stringify(text));
console.log(text);
This is improvement to Lonnie Best answer because new-line characters in his answer are not exactly the same positions as in ruby output
My extension to https://stackoverflow.com/a/15558082/80404.
It expects comment in a form /*! any multiline comment */ where symbol ! is used to prevent removing by minification (at least for YUI compressor)
Function.prototype.extractComment = function() {
var startComment = "/*!";
var endComment = "*/";
var str = this.toString();
var start = str.indexOf(startComment);
var end = str.lastIndexOf(endComment);
return str.slice(start + startComment.length, -(str.length - end));
};
Example:
var tmpl = function() { /*!
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
</ul>
</div>
*/}.extractComment();
Updated for 2015: it's six years later now: most people use a module loader, and the main module systems each have ways of loading templates. It's not inline, but the most common type of multiline string are templates, and templates should generally be kept out of JS anyway.
require.js: 'require text'.
Using require.js 'text' plugin, with a multiline template in template.html
var template = require('text!template.html')
NPM/browserify: the 'brfs' module
Browserify uses a 'brfs' module to load text files. This will actually build your template into your bundled HTML.
var fs = require("fs");
var template = fs.readFileSync(template.html', 'utf8');
Easy.
If you're willing to use the escaped newlines, they can be used nicely. It looks like a document with a page border.
Easiest way to make multiline strings in Javascrips is with the use of backticks ( `` ). This allows you to create multiline strings in which you can insert variables with ${variableName}.
Example:
let name = 'Willem';
let age = 26;
let multilineString = `
my name is: ${name}
my age is: ${age}
`;
console.log(multilineString);
compatibility :
It was introduces in ES6//es2015
It is now natively supported by all major browser vendors (except internet explorer)
Check exact compatibility in Mozilla docs here
The ES6 way of doing it would be by using template literals:
const str = `This
is
a
multiline text`;
console.log(str);
More reference here
You can use TypeScript (JavaScript SuperSet), it supports multiline strings, and transpiles back down to pure JavaScript without overhead:
var templates = {
myString: `this is
a multiline
string`
}
alert(templates.myString);
If you'd want to accomplish the same with plain JavaScript:
var templates =
{
myString: function(){/*
This is some
awesome multi-lined
string using a comment
inside a function
returned as a string.
Enjoy the jimmy rigged code.
*/}.toString().slice(14,-3)
}
alert(templates.myString)
Note that the iPad/Safari does not support 'functionName.toString()'
If you have a lot of legacy code, you can also use the plain JavaScript variant in TypeScript (for cleanup purposes):
interface externTemplates
{
myString:string;
}
declare var templates:externTemplates;
alert(templates.myString)
and you can use the multiline-string object from the plain JavaScript variant, where you put the templates into another file (which you can merge in the bundle).
You can try TypeScript at
http://www.typescriptlang.org/Playground
ES6 allows you to use a backtick to specify a string on multiple lines. It's called a Template Literal. Like this:
var multilineString = `One line of text
second line of text
third line of text
fourth line of text`;
Using the backtick works in NodeJS, and it's supported by Chrome, Firefox, Edge, Safari, and Opera.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
Also do note that, when extending string over multiple lines using forward backslash at end of each line, any extra characters (mostly spaces, tabs and comments added by mistake) after forward backslash will cause unexpected character error, which i took an hour to find out
var string = "line1\ // comment, space or tabs here raise error
line2";
Please for the love of the internet use string concatenation and opt not to use ES6 solutions for this. ES6 is NOT supported all across the board, much like CSS3 and certain browsers being slow to adapt to the CSS3 movement. Use plain ol' JavaScript, your end users will thank you.
Example:
var str = "This world is neither flat nor round. "+
"Once was lost will be found";
You can use tagged templates to make sure you get the desired output.
For example:
// Merging multiple whitespaces and trimming the output
const t = (strings) => { return strings.map((s) => s.replace(/\s+/g, ' ')).join("").trim() }
console.log(t`
This
Is
A
Multiline
String
`);
// Output: 'This Is A Multiline String'
// Similar but keeping whitespaces:
const tW = (strings) => { return strings.map((s) => s.replace(/\s+/g, '\n')).join("").trim() }
console.log(tW`
This
Is
A
Multiline
String
`);
// Output: 'This\nIs\nA\nMultiline\nString'
Multiline string with variables
var x = 1
string = string + `<label class="container">
<p>${x}</p>
</label>`;
I'm writing the JS for a chat application I'm working on in my free time, and I need to have HTML identifiers that change according to user submitted data. This is usually something conceptually shaky enough that I would not even attempt it, but I don't see myself having much of a choice this time. What I need to do then is to escape the HTML id to make sure it won't allow for XSS or breaking HTML.
Here's the code:
var user_id = escape(id)
var txt = '<div class="chut">'+
'<div class="log" id="chut_'+user_id+'"></div>'+
'<textarea id="chut_'+user_id+'_msg"></textarea>'+
'<label for="chut_'+user_id+'_to">To:</label>'+
'<input type="text" id="chut_'+user_id+'_to" value='+user_id+' readonly="readonly" />'+
'<input type="submit" id="chut_'+user_id+'_send" value="Message"/>'+
'</div>';
What would be the best way to escape id to avoid any kind of problem mentioned above? As you can see, right now I'm using the built-in escape() function, but I'm not sure of how good this is supposed to be compared to other alternatives. I'm mostly used to sanitizing input before it goes in a text node, not an id itself.
Never use escape(). It's nothing to do with HTML-encoding. It's more like URL-encoding, but it's not even properly that. It's a bizarre non-standard encoding available only in JavaScript.
If you want an HTML encoder, you'll have to write it yourself as JavaScript doesn't give you one. For example:
function encodeHTML(s) {
return s.replace(/&/g, '&').replace(/</g, '<').replace(/"/g, '"');
}
However whilst this is enough to put your user_id in places like the input value, it's not enough for id because IDs can only use a limited selection of characters. (And % isn't among them, so escape() or even encodeURIComponent() is no good.)
You could invent your own encoding scheme to put any characters in an ID, for example:
function encodeID(s) {
if (s==='') return '_';
return s.replace(/[^a-zA-Z0-9.-]/g, function(match) {
return '_'+match[0].charCodeAt(0).toString(16)+'_';
});
}
But you've still got a problem if the same user_id occurs twice. And to be honest, the whole thing with throwing around HTML strings is usually a bad idea. Use DOM methods instead, and retain JavaScript references to each element, so you don't have to keep calling getElementById, or worrying about how arbitrary strings are inserted into IDs.
eg.:
function addChut(user_id) {
var log= document.createElement('div');
log.className= 'log';
var textarea= document.createElement('textarea');
var input= document.createElement('input');
input.value= user_id;
input.readonly= True;
var button= document.createElement('input');
button.type= 'button';
button.value= 'Message';
var chut= document.createElement('div');
chut.className= 'chut';
chut.appendChild(log);
chut.appendChild(textarea);
chut.appendChild(input);
chut.appendChild(button);
document.getElementById('chuts').appendChild(chut);
button.onclick= function() {
alert('Send '+textarea.value+' to '+user_id);
};
return chut;
}
You could also use a convenience function or JS framework to cut down on the lengthiness of the create-set-appends calls there.
ETA:
I'm using jQuery at the moment as a framework
OK, then consider the jQuery 1.4 creation shortcuts, eg.:
var log= $('<div>', {className: 'log'});
var input= $('<input>', {readOnly: true, val: user_id});
...
The problem I have right now is that I use JSONP to add elements and events to a page, and so I can not know whether the elements already exist or not before showing a message.
You can keep a lookup of user_id to element nodes (or wrapper objects) in JavaScript, to save putting that information in the DOM itself, where the characters that can go in an id are restricted.
var chut_lookup= {};
...
function getChut(user_id) {
var key= '_map_'+user_id;
if (key in chut_lookup)
return chut_lookup[key];
return chut_lookup[key]= addChut(user_id);
}
(The _map_ prefix is because JavaScript objects don't quite work as a mapping of arbitrary strings. The empty string and, in IE, some Object member names, confuse it.)
You can use this:
function sanitize(string) {
const map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
"/": '/',
};
const reg = /[&<>"'/]/ig;
return string.replace(reg, (match)=>(map[match]));
}
Also see OWASP XSS Prevention Cheat Sheet.
You could use a simple regular expression to assert that the id only contains allowed characters, like so:
if(id.match(/^[0-9a-zA-Z]{1,16}$/)){
//The id is fine
}
else{
//The id is illegal
}
My example allows only alphanumerical characters, and strings of length 1 to 16, you should change it to match the type of ids that you use.
By the way, at line 6, the value property is missing a pair of quotes, an easy mistake to make when you quote on two levels.
I can't see your actual data flow, depending on context this check may not at all be needed, or it may not be enough. In order to make a proper security review we would need more information.
In general, about built in escape or sanitize functions, don't trust them blindly. You need to know exactly what they do, and you need to establish that that is actually what you need. If it is not what you need, the code your own, most of the time a simple whitelisting regex like the one I gave you works just fine.
Since the text that you are escaping will appear in an HTML attribute, you must be sure to escape not only HTML entities but also HTML attributes:
var ESC_MAP = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
function escapeHTML(s, forAttribute) {
return s.replace(forAttribute ? /[&<>'"]/g : /[&<>]/g, function(c) {
return ESC_MAP[c];
});
}
Then, your escaping code becomes var user_id = escapeHTML(id, true).
For more information, see Foolproof HTML escaping in Javascript.
You need to take extra precautions when using user supplied data in HTML attributes. Because attributes has many more attack vectors than output inside HTML tags.
The only way to avoid XSS attacks is to encode everything except alphanumeric characters. Escape all characters with ASCII values less than 256 with the &#xHH; format. Which unfortunately may cause problems in your scenario, if you are using CSS classes and javascript to fetch those elements.
OWASP has a good description of how to mitigate HTML attribute XSS:
http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.233_-_JavaScript_Escape_Before_Inserting_Untrusted_Data_into_HTML_JavaScript_Data_Values
The following approach to prevent XSS looks like a good solution.
var sanitizeHTML = function (str) {
return str.replace(/[^\w. ]/gi, function (c) {
return '&#' + c.charCodeAt(0) + ';';
});
};
Here is a working example:
var sanitizeHTML = function (str) {
return str.replace(/[^\w. ]/gi, function (c) {
return '&#' + c.charCodeAt(0) + ';';
});
};
var app = document.querySelector('#app');
app.innerHTML = sanitizeHTML('<img src="x" onerror="alert(1)">');
<div id="app">
</div>
This solution was Provided Here.
Just to add to the comment of #SilentImp. if u need a typeScript version...
export function sanitize(input: string) {
const map: Record<string, string> = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'/': '/',
};
const reg = /[&<>"'/]/gi;
return input.replace(reg, (match) => map[match]);
}
In mediawiki, is it possible to change the label of a 'Category' at the bottom of an article.
For example for the following article:
=Paris=
blablablablablabla
[[Category:place_id]]
I'd like to see something more verbose like (the example below doesn't work):
=Paris=
blablablablablabla
[[Category:place_id|France]]
Note: I don't want to use a 'redirect' and I want to keep my strange ids because they are linked to an external database.
I do not think mediawiki is supporting this feature.
However, how about using:
[[Category:France]]
in your page, and set it into the category named with your id? France would just be a subcategory of "place_id", and you could use more terms all linked to the parent category. For this, you just need to edit the category page for "France", inserting:
[[Category:place_id]]
An alternative would be to put your page in both categories, but in this case, the id would still be displayed:
[[Category:place_id]]
[[Category:France]]
You could do this with an OutputPageMakeCategoryLinks hook. Alas, the interface for that hook seems to be a bit inconvenient — as far as I can tell, it's pretty much only good for replacing the standard category link generation code entirely. Still, you could do that is you want:
function myOutputPageMakeCategoryLinks( &$out, $categories, &$links ) {
foreach ( $categories as $category => $type ) {
$title = Title::makeTitleSafe( NS_CATEGORY, $category );
$text = $title->getText();
if ( $text == 'Place id' ) {
// set $text to something else
}
$links[$type][] = Linker::link( $title, htmlspecialchars( $text ) );
}
return false; // skip default link generation
}
$wgHooks['OutputPageMakeCategoryLinks'][] = 'myOutputPageMakeCategoryLinks';
(The code above is based on the default category link generation code in OutputPage.php, somewhat simplified; I assume you're not using language variant conversion on your wiki, so I removed the parts that deal with that. Note that this code is untested! Use at your own risk.)
I have this function in my website.
function autolink($content) {
$pattern = "/>>[0-9]/i" ;
$replacement = ">>$0";
return preg_replace($pattern, $replacement, $content, -1);
This is for making certain characters into a clickable hyperlink.
For example, (on a thread) when a user inputs '>>4' to denote to the another reply number 4, the function can be useful.
But it's not working. the characters are not converted into a hyperlink. They just remain as plain text. Not clickable.
Could someone tell me what is wrong with the function?
So the objective is to convert:
This is a reference to the >>4 reply
...into:
This is a reference to the >>4 reply
...where ">" is the HTML UTF-8 equivalent of ">". (remember, you don't want to create HTML issues)
The problems: (1) you forgot to escape the quotes in the replacement (2) since you want to isolate the number, you need to use parentheses to create a sub-pattern for later reference.
Once you do this, you arrive at:
function autolink($contents) {
return preg_replace( "/>>([0-9])/i",
">>$1",
$contents,
-1
);
}
Good luck
I am a big time user of using double quotes in PHP so that I can interpolate variables rather than concatenating strings. As a result, when I am generating HTML I often use single quotes for setting tag fields. For example:
$html = "<input type='text' name='address' value='$address'>";
Now this is far more readable to me than either
$html = "<input type=\"text\" name=\"address\" value=\"$address\">";
or
$html = '<input type="text" name="address" values="' . $address . '">' ;
From brief searches I have heard people saying that single quotes for HTML fields is not recognized by EVERY browser. Thus I am wondering what browsers would have problems recognizing single quote HTML?
This is similar to When did single quotes in HTML become so popular?. Single quotes around attributes in HTML are and always have been permitted by the specification. I don't think any browsers wouldn't understand them.
As noted by PhiLho, although there is a widely spread belief that single quotes are not allowed for attribute values, that belief is wrong.
The XML standard permits both single and double quotes around attribute values.
The XHTML standard doesn't say anything to change this, but a related section which states that attribute values must be quoted uses double quotes in the example, which has probably lead to this confusion. This example is merely pointing out that attribute values in XHTML must meet the minimum standard for attribute values in XML, which means they must be quoted (as opposed to plain HTML which doesn't care), but does not restrict you to either single or double quotes.
Of course, it's always possible that you'll encounter a parser which isn't standards-compliant, but when that happens all bets are off anyway. So it's best to just stick to what the specification says. That's why we have specifications, after all.
I have heard people saying that single quotes for HTML fields is not recognized by EVERY browser
That person is wrong.
Don't believe everything you see on Internet...
Funnily, I just answered something similar to somebody declaring single quotes are not valid in XHTML...
Mmm, I look above while typing, and see that Adam N propagates the same belief. If he can back up his affirmation, I retract what I wrote... AFAIK, XML is agnostic and accepts both kinds of quote. I even tried and validated without problem an XHTML page with only single quotes.
As I was looking to find information on this in a much more recent version of the specification and it took me quite some time to find it, here it is:
From
HTML
Living Standard — Last Updated 17 September 2021
[...]
13.1.2.3 Attributes
Single-quoted attribute value syntax
The attribute name, followed by zero or more ASCII whitespace, followed by a single U+003D EQUALS SIGN character, followed by zero or more ASCII whitespace, followed by a single U+0027 APOSTROPHE character ('), followed by the attribute value, which, in addition to the requirements given above for attribute values, must not contain any literal U+0027 APOSTROPHE characters ('), and finally followed by a second single U+0027 APOSTROPHE character (').
In the following example, the type attribute is given with the single-quoted attribute value syntax:
<input type='checkbox'>
If an attribute using the single-quoted attribute syntax is to be followed by another attribute, then there must be ASCII whitespace separating the two.
https://html.spec.whatwg.org/#attributes-2
Only problem is data going into TEXT INPUT fields. Consider
<input value='it's gonna break'/>
Same with:
<input value="i say - "this is gonna be trouble" "/>
You can't escape that, you have to use htmlspecialchars.
I also tend to use single quotes in HTML and I have never experienced a problem.
I used single quotes in HTML pages and embedded JavaScripts into it and its works fine. Tested in IE9, Chrome and Firefox - seems working fine.
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'>
<title>Bethanie Inc. data : geographically linked</title>
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js'></script>
<script src='https://maps.googleapis.com/maps/api/js?v=3.11&sensor=false' type='text/javascript'></script>
<script type='text/javascript'>
// check DOM Ready
$(document).ready(function() {
// execute
(function() {
/////////////// Addresses ///////////////////
var locations = new Array();
var i = 0;
locations[i++] = 'L,Riversea: Comp Site1 at Riversea,1 Wallace Lane Mosman Park WA 6012'
locations[i++] = 'L,Wearne: Comp Site2 at Wearne,1 Gibney St Cottesloe WA 6011'
locations[i++] = 'L,Beachside:Comp Site3 Beachside,629 Two Rocks Rd Yanchep WA 6035'
/////// Addresses/////////
var total_locations = i;
i = 0;
console.log('About to look up ' + total_locations + ' locations');
// map options
var options = {
zoom: 10,
center: new google.maps.LatLng(-31.982484, 115.789329),//Bethanie
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: true
};
// init map
console.log('Initialise map...');
var map = new google.maps.Map(document.getElementById('map_canvas'), options);
// use the Google API to translate addresses to GPS coordinates
//(See Limits: https://developers.google.com/maps/documentation/geocoding/#Limits)
var geocoder = new google.maps.Geocoder();
if (geocoder) {
console.log('Got a new instance of Google Geocoder object');
// Call function 'createNextMarker' every second
var myVar = window.setInterval(function(){createNextMarker()}, 700);
function createNextMarker() {
if (i < locations.length)
{
var customer = locations[i];
var parts = customer.split(','); // split line into parts (fields)
var type= parts.splice(0,1); // type from location line (remove)
var name = parts.splice(0,1); // name from location line(remove)
var address =parts.join(','); // combine remaining parts
console.log('Looking up ' + name + ' at address ' + address);
geocoder.geocode({ 'address': address }, makeCallback(name, type));
i++; // next location in list
updateProgressBar(i / total_locations);
} else
{
console.log('Ready looking up ' + i + ' addresses');
window.clearInterval(myVar);
}
}
function makeCallback(name,type)
{
var geocodeCallBack = function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var longitude = results[0].geometry.location.lng();
var latitude = results[0].geometry.location.lat();
console.log('Received result: lat:' + latitude + ' long:' + longitude);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(latitude, longitude),
map: map,
title: name + ' : ' + '\r\n' + results[0].formatted_address});// this is display in tool tip/ icon color
if (type=='E') {marker.setIcon('http://maps.google.com/mapfiles/ms/icons/green-dot.png')};
Recently i've experienced a problem with Google Search optimization. If has a single quotes, it doesn't seem to crawl linked pages.
... or just use heredocs. Then you don't need to worry about escaping anything but END.
Single Quotes are fine for HTML, but they don't make valid XHTML, which might be problematic if anybody was using a browser which supported only XHTML, but not HTML. I don't believe any such browsers exist, though there are probably some User-Agents out there that do require strict XHTML.