Open D-32 opened 9 years ago
It goes into 'capitalize the next letter' mode, which is what mobile keyboards tend to do when at the start of what looks like a sentence. I don't think there is a way for CodeMirror to suppress this, but if you do know of one, tell me.
That would make sense, but it stays in caps lock. So if I type A the next character is still upper case. Which is annoying, as the user manually has to get out of that mode. This surely isn't an intended behavior.
That is indeed odd. I'll see if I can figure out what is happening the next time I have my iPad in my hand.
Thanks :)
Seems related to this bug filed against WebKit: https://bugs.webkit.org/show_bug.cgi?id=148503
Switching to inputStyle: "textarea" resolves this issue, but produces the issue where the native cursor is displayed in addition to the codemirror cursor. I might be willing to live with that by disabling the codemirror cursor, but perhaps there are other problems I haven't discovered yet since textarea is not the default on mobile?
edit: at least one thing that stops working correctly in mobile with "textarea" mode is text selection.
I've met same issue. The problem is that if e.preventDefault is called - then iOS will skip internal callbacks and will NOT switch case to lower.
For CM4 I've made a workaround for CM keypress event like this
onKeyPress: function(e) {
if (capitalizationHack.isPreventDefaultNeeded(e)){ // if uppercase -> not needed
e.preventDefault();
}
operation(....)
},
And after this - we have two events of adding letter. The extra letter should be removed
if (cm.capitalizationHack.isHackEnabled()) {
CodeMirror.on(cm.doc, 'change', function (instance, change) {
var capHack = this.editor.capitalizationHack;
if (capHack.isDuplicateChange() && (change.text.length == 1)) {
console.log("Line BF: " + cm.getLine(change.from.line));
var realFrom = {
line: change.from.line,
ch: change.from.ch - 1
};
var realTo = {
line: change.from.line,
ch: change.from.ch + 1
};
cm.replaceRange(change.text[0], realFrom, realTo);
console.log("Line AF: " + cm.getLine(change.from.line));
}
}.bind(this));
}
This is definitely ugly hack. But first seems to be working ok for user. I hope that CM authors will think how to process this situation in a more beautiful way.
If necessary - I can provide full code of workaround. Most likely in CM5 - the situation is the same.
@boucher @marijnh @D-32 FYI
@denis-aes Would it be possible for you to provide the full code workaround for this issue? This has become a very problematic bug for a current project and we're attempting to patch. Any further code snippets/file would be much appreciated.
@sassywebgal it has changed a little. We removed preventing. But now always remove duplicate symbols:
Main logic in codemirror.js
var isSafariOrWebview = /(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent);
if (_isCapsHackEnabled) {
var capitalizationHack = (new function capitalizationHack() {
var changeNum = 0;
var eventPressed;
this.isHackEnabled = function () {return _isCapsHackEnabled;};
this.processKeyUp = function () {
changeNum = 0;
eventPressed = false;
};
this.isDuplicateChange = function () {
if (eventPressed) {
changeNum++;
return changeNum == 2;
}
};
}());
}
else{
var capitalizationHack = {
isHackEnabled: function () {return _isCapsHackEnabled;},
processKeyUp: function () {},
isDuplicateChange: function () {},
isPreventDefaultNeeded: function () {return true}
}
}
Also you should fix onKeyUp:
function onKeyUp(e) {
if (e.keyCode == 16) this.doc.sel.shift = false;
capitalizationHack.processKeyUp(e); //this line added
signalDOMEvent(this, e);
}
And in client code, where you create CodeMirror instance, do:
CodeMirror.on(cm.doc, 'beforeChange', function(instance, e) {
if (cm.capitalizationHack && cm.capitalizationHack.isHackEnabled()) {
var capHack = this.editor.capitalizationHack;
if (capHack.isDuplicateChange() && (e.text.length == 1)) {
e.update({
ch: e.from.ch - 1,
line: e.from.line
},{
ch: e.from.ch,
line: e.from.line
},'');
}
}
});
Try it. I hope will help.
@denis-aes do you have any CodeMirror.js for me to take a look? I can't get it to work. Thanks!
I have the same problem, i didn't find how to make the @denis-aes's patch work but I find another ugly way by re-focus the editor after the user type the first character on a line :
editor.on('change', function(instance, change) {
var line = editor.getLine(change.from.line);
if(line.length === 1 && change.text.length === 1 && (/^[A-Z]$/).test(change.text[0])){
var focused = $(':focus');
focused.blur();
focused.focus();
}
});
See also this ProseMirror issue for context. There we ended up half-fixing it by letting native edit events go through, and patching up the DOM after the fact. We might also eventually want to do something like that in CodeMirror, but I'm not sure when I'll have time for it. Also, this still won't solve the problem of the keyboard case being stuck when programatically moving the cursor. And the blur/focus hack is too slow to apply it every time it'd be needed.
In the end, this is a really stupid bug in Mobile Safari, and because Apple doesn't appear to have an open bug tracker for stuff like this, it's rather hard to figure out whether they are aware of the issue and intend to look into it. If you have an Apple account and some time on your hands, firing more bug reports their way might help: https://developer.apple.com/bug-reporting/ (the precise issue, which can easily be reproduced outside of CodeMirror, is that if you change the DOM selection with JavaScript, as opposed to the user doing it directly, that doesn't cause the keyboard state -- such as default case -- to update)
This seems fixed now?
Does someone who participated in this thread have a stable solution that works with the latest version of CodeMirror and that they can recommend?
We are working on a rewrite (CodeMirror 6) that will probably address this issue, and we are currently raising money for this work: See the announcement for more information about the rewrite and a demo.
Note that CodeMirror 6 is by no means stable or usable in production, yet. It's highly unlikely that we pick up this issue for CodeMirror 5, though.
Note that, unless this was fixed in the meantime, Mobile Safari is pretty awful about syncing up the automatic capitalization with programmatic selection updates—it tends to leave that in the state it was at the last user-driven cursor change or user input. So this'll work much better in version 6 than it does now (tapping or typing gives the expected result), but if yours scripts move the cursor somewhere, there might still be flakiness.
Yeah - been using this recently, and the ios experience is not great
Just to clarify: You tried out the CodeMirror 6 demo and found issues under iOS?
Darn no - version 5. Is the dsl of 5 wildly different in 6?
CodeMirror 6 is a complete rewrite, and it's currently under development. You can have a look at the announcement with embedded demo, and I would like to know how it works in iOS :)
Just checked the Demo on my iPhone and it seems to work fine.
For the maintainers, might it make sense to have a label and/or title/description blurb to mark issues that are addressed by version 6 to improve clarity?
Edit: Just noticed the “Fixed in rewrite (hopefully)” milestone 🙏
[SOLVED]
I have fixed this issue in one of my project. We just need to set autocapitalize
to off
for the input field which is used by codemirror. Here is how it can be done -
let editor = CodeMirror($el, { options });
let $input = editor.getInputField();
$input.setAttribute('autocapitalize', 'off');
If you want to turn off auto correct-
$input.setAttribute('autocorrect', 'off');
Enjoy !! 🥂
Oh, wow, CodeMirror was setting these to "false"
, which is apparently ignored because the attribute expects "off"
(contrary to spellcheck
or contenteditable
, which do use "false"
🙄).
Attached patch fixes this.
I think this issue can be closed as well? https://github.com/codemirror/CodeMirror/issues/4865
Hey guys, how to apply this fix to version 6?
An extension like EditorView.contentAttributes.of({autocapitalize: "off", autocorrect: "off"})
should work I think.
When focusing onto an empty line on an iOS device inside WKWebview or Safari the keyboard switches to all caps mode. This can be reproduced easily in the example on http://codemirror.net. Just tap somewhere next to the last line, the cursor will focus as seen on the attached screenshot and the keyboard goes into all caps mode.