diff --git a/js/utils/events.js b/js/utils/events.js
index c4014fccf8..d2def899ec 100644
--- a/js/utils/events.js
+++ b/js/utils/events.js
@@ -3,7 +3,7 @@
*
* Author: Max Lynch
*
- * Framework events handles various mobile browser events, and
+ * Framework events handles various mobile browser events, and
* detects special events like tap/swipe/etc. and emits them
* as custom events that can be used in an app.
*
@@ -48,14 +48,18 @@
VIRTUALIZED_EVENTS: ['tap', 'swipe', 'swiperight', 'swipeleft', 'drag', 'hold', 'release'],
// Trigger a new event
- trigger: function(eventType, data) {
- var event = new CustomEvent(eventType, { detail: data });
+ trigger: function(eventType, data, bubbles, cancelable) {
+ var event = new CustomEvent(eventType, {
+ detail: data,
+ bubbles: !!bubbles,
+ cancelable: !!cancelable
+ });
// Make sure to trigger the event on the given target, or dispatch it from
// the window if we don't have an event target
data && data.target && data.target.dispatchEvent(event) || window.dispatchEvent(event);
},
-
+
// Bind an event
on: function(type, callback, element) {
var e = element || window;
@@ -92,8 +96,8 @@
handlePopState: function(event) {
},
};
-
-
+
+
// Map some convenient top-level functions for event handling
ionic.on = function() { ionic.EventController.on.apply(ionic.EventController, arguments); };
ionic.off = function() { ionic.EventController.off.apply(ionic.EventController, arguments); };
diff --git a/js/utils/keyboard.js b/js/utils/keyboard.js
new file mode 100644
index 0000000000..a1c3e01240
--- /dev/null
+++ b/js/utils/keyboard.js
@@ -0,0 +1,52 @@
+(function(ionic) {
+
+ionic.Platform.ready(function() {
+ if (ionic.Platform.is('android')) {
+ androidKeyboardFix();
+ }
+});
+
+function androidKeyboardFix() {
+ var rememberedDeviceWidth = window.innerWidth;
+ var rememberedDeviceHeight = window.innerHeight;
+ var keyboardHeight;
+
+ window.addEventListener('resize', resize);
+
+ function resize() {
+
+ //If the width of the window changes, we have an orientation change
+ if (rememberedDeviceWidth !== window.innerWidth) {
+ rememberedDeviceWidth = window.innerWidth;
+ rememberedDeviceHeight = window.innerHeight;
+ console.info('orientation change. deviceWidth =', rememberedDeviceWidth,
+ ', deviceHeight =', rememberedDeviceHeight);
+
+ //If the height changes, and it's less than before, we have a keyboard open
+ } else if (rememberedDeviceHeight !== window.innerHeight &&
+ window.innerHeight < rememberedDeviceHeight) {
+ document.body.classList.add('hide-footer');
+ //Wait for next frame so document.activeElement is set
+ window.rAF(handleKeyboardChange);
+ } else {
+ //Otherwise we have a keyboard close or a *really* weird resize
+ document.body.classList.remove('hide-footer');
+ }
+
+ function handleKeyboardChange() {
+ //keyboard opens
+ keyboardHeight = rememberedDeviceHeight - window.innerHeight;
+ var activeEl = document.activeElement;
+ if (activeEl) {
+ //This event is caught by the nearest parent scrollView
+ //of the activeElement
+ ionic.trigger('scrollChildIntoView', {
+ target: activeEl
+ }, true);
+ }
+
+ }
+ }
+}
+
+})(window.ionic);
diff --git a/js/views/scrollView.js b/js/views/scrollView.js
index 446675ae25..c31e853d02 100644
--- a/js/views/scrollView.js
+++ b/js/views/scrollView.js
@@ -593,6 +593,28 @@ ionic.views.Scroll = ionic.views.View.inherit({
// Event Handler
var container = this.__container;
+ //Broadcasted when keyboard is shown on some platforms.
+ //See js/utils/keyboard.js
+ container.addEventListener('scrollChildIntoView', function(e) {
+ var deviceHeight = window.innerHeight;
+ var element = e.target;
+ var elementHeight = e.target.offsetHeight;
+
+ //getBoundingClientRect() will actually give us position relative to the viewport
+ var elementDeviceTop = element.getBoundingClientRect().top;
+ var elementScrollTop = ionic.DomUtil.getPositionInParent(element, container).top;
+
+ //If the element is positioned under the keyboard...
+ if (elementDeviceTop + elementHeight > deviceHeight) {
+ //Put element in middle of visible screen
+ self.scrollTo(0, elementScrollTop + elementHeight - (deviceHeight * 0.5), true);
+ }
+
+ //Only the first scrollView parent of the element that broadcasted this event
+ //(the active element that needs to be shown) should receive this event
+ e.stopPropagation();
+ });
+
if ('ontouchstart' in window) {
container.addEventListener("touchstart", function(e) {
diff --git a/scss/_util.scss b/scss/_util.scss
index fa84a34f6d..40472910ef 100644
--- a/scss/_util.scss
+++ b/scss/_util.scss
@@ -4,9 +4,9 @@
* --------------------------------------------------
*/
-.hidden,
-.hide {
- display: none;
+.hidden,
+.hide {
+ display: none;
}
.show {
display: block;
@@ -15,6 +15,17 @@
visibility: hidden;
}
+.hide-footer {
+ .bar-footer,
+ .tabs {
+ display: none;
+ }
+ .has-footer,
+ .has-tabs {
+ bottom: 0;
+ }
+}
+
.inline {
display: inline-block;
}
@@ -30,10 +41,10 @@
.block {
display: block;
clear: both;
- &:after {
- display: block;
- visibility: hidden;
- clear: both;
+ &:after {
+ display: block;
+ visibility: hidden;
+ clear: both;
height: 0;
content: ".";
}
@@ -101,8 +112,8 @@
/**
* Utility Colors
* --------------------------------------------------
- * Utility colors are added to help set a naming convention. You'll
- * notice we purposely do not use words like "red" or "blue", but
+ * Utility colors are added to help set a naming convention. You'll
+ * notice we purposely do not use words like "red" or "blue", but
* instead have colors which represent an emotion or generic theme.
*/
diff --git a/test/inputs.html b/test/inputs.html
new file mode 100644
index 0000000000..808fd86498
--- /dev/null
+++ b/test/inputs.html
@@ -0,0 +1,84 @@
+
+
+
+ List
+
+
+
+
+
+
+
+
+
+
+
+