Is there a good way to disable the "Smart Punctuation" the iOS 11 Apple Keyboard generates - in Safari on an HTML login form - username field in particular?
The problem is that we have users with apostrophes in their usernames. Typing their usernames on iOS 11 and not knowing the subtleties of unicode they are not able to sign in.
Ideally we could just instruct such users to disable smart quotes or type the proper character by holding down the apostrophe key - but I am working on educational software for small children and that is out of the question.
The problem is compounded by the fact that there are also a small selection of users with actual curly single quotes in their usernames, so a simple map of replacements won't work - and we can't canonicalize the usernames as they come from a number of external systems we don't control / can't have a lot of say over.
Disable smart quotes on iPad and iPhoneGo to Settings > General > Keyboard, and toggle off “Smart Punctuation.”
iOS 11 finally added a long-awaited feature for those of us who care about typographic details: smart punctuation. You can turn this on in Settings → General → Keyboards.
Last one to consider in the basic settings is the iPhone's "Smart Punctuation" abilities. This simply means your iPhone automatically corrects certain punctuation marks to be more visually pleasing.
I don't want the English curly quotes. Just the same upright apostrophes and quotes as on Windows. On an iPhone/iPad screen keyboard, tap the 123 button and then press and hold the keys that show quote marks. You should get a popup menu where you can choose the straight ones that you want.
Unfortunately according to this MDN page there is no known Webkit <input>
or <textarea>
attributes to disable smart-quotes, but you can patch it with a script I've written derived from this QA: How to disable smart quotes for textarea fields in the browser?
window.addEventListener('DOMContentLoaded', attachFilterToInputs );
function attachFilterToInputs() {
var textInputs = document.querySelectorAll( 'input[type=text], input[type=password], input[type=email], input[type=search], input[type=url], textarea, *[contenteditable=true]' );
for( var i = 0; i < textInputs.length; i++ ) {
textInputs[i].addEventListener( 'keypress', preventPretentiousPunctuation );
}
}
var conversionMap = createConversionMap();
function createConversionMap() {
var map = {};
// Open-quotes: http://www.fileformat.info/info/unicode/category/Pi/list.htm
map[ 0x2018 ] = '\'';
map[ 0x201B ] = '\'';
map[ 0x201C ] = '"';
map[ 0x201F ] = '"';
// Close-quotes: http://www.fileformat.info/info/unicode/category/Pf/list.htm
map[ 0x2019 ] = '\'';
map[ 0x201D ] = '\"';
// Primes: http://www.fileformat.info/info/unicode/category/Po/list.htm
map[ 0x2032 ] = '\'';
map[ 0x2033 ] = '"';
map[ 0x2035 ] = '\'';
map[ 0x2036 ] = '"';
map[ 0x2014 ] = '-'; // iOS 11 also replaces dashes with em-dash
map[ 0x2013 ] = '-'; // and "--" with en-dash
return map;
}
function preventPretentiousPunctuation( event ) {
if( event.key.length != 1 ) return;
var code = event.key.codePointAt(0);
var replacement = conversionMap[ code ];
if( replacement ) {
event.preventDefault();
document.execCommand( 'insertText', 0, replacement );
}
}
Thanks to Dai for the outline of the answer. Unfortunately when we implemented their solution and tested on an iOS 11 device, we found that the keypress
event listener wasn't firing at all. We reworked their solution using the input
event and regex string replace and found this did work for us.
Here is our variation, using jQuery for the selector and a shorter replace list.
<script type="text/javascript">
// Here are the reference to Unicode Characters in the Punctuation
// Open-quotes: http://www.fileformat.info/info/unicode/category/Pi/list.htm
// Close-quotes: http://www.fileformat.info/info/unicode/category/Pf/list.htm
window.addEventListener('DOMContentLoaded', attachFilterToInputs);
// Patch the iOS Smart Punctuation functionality on restricted field(s),
// so that the user types acceptable characters.
function attachFilterToInputs() {
try {
$("[name$='MyProtectedFieldName']").on('input', preventPretentiousPunctuation);
}
catch (err) {
// do nothing
}
}
function preventPretentiousPunctuation(event) {
try {
var str = $(this).val();
var replacedStr = "";
replacedStr = str.replace(/[\u2018\u2019\u201C\u201D]/g,
(c) => '\'\'""'.substr('\u2018\u2019\u201C\u201D'.indexOf(c), 1));
if (str !== replacedStr) {
$(this).val(replacedStr);
}
}
catch (err) {
// do nothing
}
}
</script>
Adding as an answer since I don't have the rep to comment.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With