forked from jouni/j-elements
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
iOS keyboard height detection prototype
Non-functional at the moment, but the concept how it could be possible (very ugly)
- Loading branch information
Showing
1 changed file
with
95 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// From: https://stackoverflow.com/questions/9038625/detect-if-device-is-ios#9039885 | ||
function iOS() { | ||
var iDevices = [ | ||
'iPad Simulator', | ||
'iPhone Simulator', | ||
'iPod Simulator', | ||
'iPad', | ||
'iPhone', | ||
'iPod' | ||
]; | ||
|
||
if (!!navigator.platform) { | ||
while (iDevices.length) { | ||
if (navigator.platform === iDevices.pop()){ return true; } | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
let measureElement; | ||
const keyboardHeight = { portrait: -1, landscape: -1 }; | ||
let measuring = false; | ||
|
||
/** | ||
* Measures the software keyboard height on iOS. The value is measured once for portrait and | ||
* landscape orientation, and after that a cached value is used. | ||
* | ||
* You need to call this method during the same event loop when a user-originated focus event is | ||
* processed (it's not possible to force the software keyboard visible by calling input.focus()). | ||
* | ||
* A scroll event listener on the window object together with document.body.scrollTop is used to | ||
* measure the keyboard height. | ||
* | ||
* @return {Promise} A promise which resolves with the measured keyboard height | ||
*/ | ||
export function measureKeyboardHeight(originalFocusTarget) { | ||
// This script is tailored for iOS only | ||
// You should be able to get the keyboard height on Android using standard DOM APIs | ||
// (window.clientHeight etc) | ||
// TODO use the standard DOM APIs on Android to return a sensible value | ||
if (!iOS() || measuring) { | ||
return new Promise((resolve, reject) => { | ||
console.log(originalFocusTarget) | ||
reject(measuring ? 'Already measuring' : 'Only supported/needed on iOS'); | ||
}); | ||
}; | ||
|
||
measuring = true; | ||
|
||
const orientation = Math.abs(window.orientation) == 90 ? 'landscape' : 'portrait'; | ||
|
||
// Return the cached value | ||
if (keyboardHeight[orientation] > 0) { | ||
return new Promise((resolve) => { | ||
resolve(keyboardHeight[orientation]); | ||
}); | ||
} | ||
|
||
if (!measureElement) { | ||
measureElement = document.createElement('input'); | ||
measureElement.style.position = 'absolute'; | ||
measureElement.style.bottom = '0'; | ||
measureElement.style.margin = '0'; | ||
// measureElement.style.fontSize = '20px'; | ||
// measureElement.style.opacity = '0'; | ||
// measureElement.style.pointerEvents = 'none'; | ||
} | ||
|
||
document.body.appendChild(measureElement); | ||
document.body.style.position = 'relative'; | ||
measureElement.focus(); | ||
|
||
return new Promise((resolve) => { | ||
// setTimeout(function() { | ||
// document.body.getBoundingClientRect(); | ||
// console.log(document.body.scrollTop); | ||
// // keyboardHeight[orientation] = document.body.scrollTop; | ||
// resolve(keyboardHeight[orientation]); | ||
// measureElement.style.position = originalStyle.position; | ||
// measureElement.style.bottom = originalStyle.bottom; | ||
// }, 300); | ||
window.addEventListener('scroll', function scrollListener() { | ||
window.removeEventListener('scroll', scrollListener); | ||
const offset = document.body.getBoundingClientRect(); | ||
console.log(offset, document.body.scrollTop); | ||
// keyboardHeight[orientation] = document.body.scrollTop; | ||
resolve(keyboardHeight[orientation]); | ||
document.body.removeChild(measureElement); | ||
document.body.style.position = ''; | ||
originalFocusTarget.focus(); | ||
measuring = false; | ||
}); | ||
}); | ||
} |