From a7f6e1c7c607296bdda130713d92580579b4079f Mon Sep 17 00:00:00 2001 From: Tim Lancina Date: Mon, 28 Apr 2014 15:56:19 -0500 Subject: [PATCH 01/10] get keyboard wip stuff working decently on android --- js/utils/keyboard.js | 36 +++++++++++++++++++++++++----------- js/views/scrollView.js | 6 ++++-- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/js/utils/keyboard.js b/js/utils/keyboard.js index a7f367ccbb..b366848303 100644 --- a/js/utils/keyboard.js +++ b/js/utils/keyboard.js @@ -57,8 +57,10 @@ function keyboardSetShow(e) { keyboardFocusInTimer = setTimeout(function(){ var keyboardHeight = keyboardGetHeight(); var elementBounds = keyboardActiveElement.getBoundingClientRect(); - - keyboardShow(e.target, elementBounds.top, elementBounds.bottom, keyboardViewportHeight, keyboardHeight); + + setTimeout(function(){ + keyboardShow(e.target, elementBounds.top, elementBounds.bottom, keyboardViewportHeight, keyboardHeight); + }, (ionic.Platform.isIOS() ? 0 : 350)); }, 32); } @@ -77,7 +79,7 @@ function keyboardShow(element, elementTop, elementBottom, viewportHeight, keyboa } else { // view's height was shrunk down and the keyboard takes up the space the view doesn't fill // do not add extra padding at the bottom of the scroll view, native already did that - details.contentHeight = viewportHeight; + details.contentHeight = window.innerHeight; } console.debug('keyboardShow', keyboardHeight, details.contentHeight); @@ -169,12 +171,8 @@ function keyboardGetHeight() { } return 216; } else if( ionic.Platform.isAndroid() ) { - if( ionic.Platform.isWebView() ) { - return 220; - } - if( ionic.Platform.version() <= 4.3) { - return 230; - } + //guess for now + return 275; } // safe guess @@ -192,8 +190,24 @@ function keyboardIsWithinScroll(ele) { } function keyboardIsOverWebView() { - return ( ionic.Platform.isIOS() ) || - ( ionic.Platform.isAndroid() && !ionic.Platform.isWebView() ); + if (ionic.Platform.isIOS()){ + if ( ionic.Platform.isWebView() ){ + //6.1 is over webview + return (ionic.Platform.version() < 7.0); + } + else { + //safari is always over webview + return true; + } + } + + if ( ionic.Platform.isAndroid() && ionic.Platform.isWebView() ){ + return ionic.Platform.isFullScreen; + } + + return false; + + } function keyboardHasPlugin() { diff --git a/js/views/scrollView.js b/js/views/scrollView.js index fb76860e8a..d7d38acb3c 100644 --- a/js/views/scrollView.js +++ b/js/views/scrollView.js @@ -629,8 +629,10 @@ ionic.views.Scroll = ionic.views.View.inherit({ if( !self.isScrolledIntoView ) { // shrink scrollview so we can actually scroll if the input is hidden // if it isn't shrink so we can scroll to inputs under the keyboard - container.style.height = (container.clientHeight - e.detail.keyboardHeight) + "px"; - container.style.overflow = "visible"; + if (ionic.Platform.isIOS() || ionic.Platform.isFullScreen){ + container.style.height = (container.clientHeight - e.detail.keyboardHeight) + "px"; + container.style.overflow = "visible"; + } self.isScrolledIntoView = true; //update scroll view self.resize(); From 14782d47c61f14e440ae58eca046fefd7c86f445 Mon Sep 17 00:00:00 2001 From: Tim Lancina Date: Mon, 28 Apr 2014 16:20:16 -0500 Subject: [PATCH 02/10] keyboard tests quickfix --- test/unit/utils/keyboard.unit.js | 44 ++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/test/unit/utils/keyboard.unit.js b/test/unit/utils/keyboard.unit.js index 9b10221f85..f419083d5a 100644 --- a/test/unit/utils/keyboard.unit.js +++ b/test/unit/utils/keyboard.unit.js @@ -41,6 +41,31 @@ Tested On - Android 4.2 Cordova +iOS 7.1 Cordova with AND without viewport height DOES resize, DOES NOT fire resize event +iOS 7.1 Safari with AND without viewport height DOES NOT resize + +iOS 7.0 Cordova with viewport height DOES resize, DOES fire resize event +iOS 7.0 Cordova without viewport height DOES resize, DOES NOT fire resize event +iOS 7.0 Safari with AND without viewport height DOES NOT resize + +iOS 6.1 Cordova with AND without viewport height DOES NOT resize +iOS 6.1 Safari without viewport height DOES NOT resize + +NOTES: + -iOS 7.1 Safari with viewport height screws up ionic layout + -iOS 7.0 Safari with viewport height, the scroll view does not resize properly on keyboardhide + -iOS 7.0 Cordova without viewport height, scroll view does not resize properly switching inputs at bottom of page + -iOS 6.1 Cordova and Safari don't work well with viewport height + +RECOMMENDATIONS: + -iOS 7.1 Cordova no viewport height, keyboard is not over webview + -iOS 7.1 Safari no viewport height, keyboard is over webview + + -iOS 7.0 Cordova yes viewport height, keyboard is not over webview + -iOS 7.0 Safari no viewport height, keyboard is over webview + + -iOS 6.1 Cordova no viewport height, keyboard is over webview + -iOS 6.1 Safari no viewport height, keyboard is over webview Notes: --------------------------------- @@ -90,16 +115,29 @@ describe('Ionic Keyboard', function() { expect( ionic.Platform.isIOS() ).toEqual(false); - expect( keyboardIsOverWebView() ).toEqual(true); + expect( keyboardIsOverWebView() ).toEqual(false); }); - it('Should keyboardIsOverWebView()=false if Android and isWebView', function(){ + it('Should keyboardIsOverWebView()=true if Android and isWebView and isFullScreen', function(){ // Android webview gets shrunk by cordova and the keyboard fills the gap ionic.Platform.setPlatform('Android'); window.cordova = {}; expect( ionic.Platform.isAndroid() ).toEqual(true); expect( ionic.Platform.isWebView() ).toEqual(true); + ionic.Platform.isFullScreen = true; + + expect( keyboardIsOverWebView() ).toEqual(true); + }); + + it('Should keyboardIsOverWebView()=false if Android and isWebView and not isFullScreen', function(){ + // Android webview gets shrunk by cordova and the keyboard fills the gap + ionic.Platform.setPlatform('Android'); + window.cordova = {}; + expect( ionic.Platform.isAndroid() ).toEqual(true); + expect( ionic.Platform.isWebView() ).toEqual(true); + ionic.Platform.isFullScreen = false; + expect( keyboardIsOverWebView() ).toEqual(false); }); @@ -171,6 +209,7 @@ describe('Ionic Keyboard', function() { var elementBottom = 200; var keyboardHeight = 200; var deviceHeight = 500; + window.innerHeight = 500; var details = keyboardShow(element, elementTop, elementBottom, deviceHeight, keyboardHeight); expect( details.isElementUnderKeyboard ).toEqual(false); @@ -182,6 +221,7 @@ describe('Ionic Keyboard', function() { var elementBottom = 400; var keyboardHeight = 200; var deviceHeight = 260; + window.innerHeight = 260; var details = keyboardShow(element, elementTop, elementBottom, deviceHeight, keyboardHeight); expect( details.contentHeight ).toEqual(260); From c9e07e810ee4f485a5d9fab19d5f62c6ff222e6a Mon Sep 17 00:00:00 2001 From: Tim Lancina Date: Tue, 29 Apr 2014 15:43:51 -0500 Subject: [PATCH 03/10] poll for window height change on android --- js/utils/keyboard.js | 96 ++++++++++++++++++++++++++++++------------ js/views/scrollView.js | 8 ++-- 2 files changed, 73 insertions(+), 31 deletions(-) diff --git a/js/utils/keyboard.js b/js/utils/keyboard.js index b366848303..26eee24fed 100644 --- a/js/utils/keyboard.js +++ b/js/utils/keyboard.js @@ -16,7 +16,8 @@ var SCROLL_CONTAINER_CSS = 'scroll'; ionic.keyboard = { isOpen: false, - height: null + height: null, + landscape: false, }; function keyboardInit() { @@ -55,12 +56,25 @@ function keyboardSetShow(e) { clearTimeout(keyboardFocusOutTimer); keyboardFocusInTimer = setTimeout(function(){ - var keyboardHeight = keyboardGetHeight(); + var keyboardHeight; var elementBounds = keyboardActiveElement.getBoundingClientRect(); - - setTimeout(function(){ - keyboardShow(e.target, elementBounds.top, elementBounds.bottom, keyboardViewportHeight, keyboardHeight); - }, (ionic.Platform.isIOS() ? 0 : 350)); + var count = 0; + + var pollKeyboardHeight = setInterval(function(){ + + keyboardHeight = keyboardGetHeight(); + if (count > 10){ + clearInterval(pollKeyboardHeight); + //waited long enough, just guess + keyboardHeight = 275; + } + if (keyboardHeight){ + keyboardShow(e.target, elementBounds.top, elementBounds.bottom, keyboardViewportHeight, keyboardHeight); + clearInterval(pollKeyboardHeight); + } + count++; + + }, 100); }, 32); } @@ -72,15 +86,7 @@ function keyboardShow(element, elementTop, elementBottom, viewportHeight, keyboa keyboardHeight: keyboardHeight }; - if( keyboardIsOverWebView() ) { - // keyboard sits on top of the view, but doesn't adjust the view's height - // lower the content height by subtracting the keyboard height from the view height - details.contentHeight = viewportHeight - keyboardHeight; - } else { - // view's height was shrunk down and the keyboard takes up the space the view doesn't fill - // do not add extra padding at the bottom of the scroll view, native already did that - details.contentHeight = window.innerHeight; - } + details.contentHeight = viewportHeight - keyboardHeight; console.debug('keyboardShow', keyboardHeight, details.contentHeight); @@ -151,28 +157,66 @@ function keyboardPreventDefault(e) { } function keyboardOrientationChange() { - keyboardViewportHeight = window.innerHeight; - setTimeout(function(){ - keyboardViewportHeight = window.innerHeight; - }, 999); + var updatedViewportHeight = window.innerHeight; + + //too slow, have to wait for updated height + if (updatedViewportHeight === keyboardViewportHeight){ + var count = 0; + var pollViewportHeight = setInterval(function(){ + //give up + if (count > 10){ + clearInterval(pollViewportHeight); + } + + updatedViewportHeight = window.innerHeight; + + if (updatedViewportHeight !== keyboardViewportHeight){ + if (updatedViewportHeight < keyboardViewportHeight){ + ionic.keyboard.landscape = true; + } + else { + ionic.keyboard.landscape = false; + } + keyboardViewportHeight = updatedViewportHeight; + clearInterval(pollViewportHeight); + } + count++; + + }, 50); + } + else { + keyboardViewportHeight = updatedViewportHeight; + } } function keyboardGetHeight() { // check if we are already have a keyboard height from the plugin - if (ionic.keyboard.height ) { + if ( ionic.keyboard.height ) { return ionic.keyboard.height; } + if ( ionic.Platform.isAndroid() ){ + //should be using the plugin, no way to know how big the keyboard is, so guess + if ( ionic.Platform.isFullScreen ){ + return 275; + } + //otherwise, wait for the screen to resize + if ( window.innerHeight < keyboardViewportHeight ){ + return keyboardViewportHeight - window.innerHeight; + } + else { + return 0; + } + } + // fallback for when its the webview without the plugin // or for just the standard web browser if( ionic.Platform.isIOS() ) { - if( ionic.Platform.isWebView() ) { - return 260; + if ( ionic.keyboard.landscape ){ + return 206; } - return 216; - } else if( ionic.Platform.isAndroid() ) { - //guess for now - return 275; + + return 260; } // safe guess diff --git a/js/views/scrollView.js b/js/views/scrollView.js index d7d38acb3c..ae3caa0a40 100644 --- a/js/views/scrollView.js +++ b/js/views/scrollView.js @@ -632,10 +632,10 @@ ionic.views.Scroll = ionic.views.View.inherit({ if (ionic.Platform.isIOS() || ionic.Platform.isFullScreen){ container.style.height = (container.clientHeight - e.detail.keyboardHeight) + "px"; container.style.overflow = "visible"; + //update scroll view + self.resize(); } self.isScrolledIntoView = true; - //update scroll view - self.resize(); } //If the element is positioned under the keyboard... @@ -651,9 +651,7 @@ ionic.views.Scroll = ionic.views.View.inherit({ ionic.tap.cloneFocusedInput(container, self); self.scrollBy(0, scrollTop, true); self.onScroll(); - }, - (ionic.Platform.isIOS() ? 80 : 350) - ); + }, 80 ); } //Only the first scrollView parent of the element that broadcasted this event From 22322610c82d651ea2c8c9b537cf13a29f1aedbe Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 30 Apr 2014 13:40:53 -0500 Subject: [PATCH 04/10] remove console.log --- js/utils/activator.js | 1 - 1 file changed, 1 deletion(-) diff --git a/js/utils/activator.js b/js/utils/activator.js index 20a99f67fb..49a64dd9d4 100644 --- a/js/utils/activator.js +++ b/js/utils/activator.js @@ -68,7 +68,6 @@ } function activateElements() { - console.log('ACTIVATING'); // activate all elements in the queue for(var key in queueElements) { if(queueElements[key]) { From 0ad10edefcdcc67d20fb837f635609974af5dbd7 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 30 Apr 2014 14:04:32 -0500 Subject: [PATCH 05/10] fix(viewport): Remove height value on iOS browser --- js/utils/viewport.js | 21 +++++++++++++-------- test/unit/utils/keyboard.unit.js | 22 +++++----------------- test/unit/utils/viewport.unit.js | 20 ++++++++++++++++---- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/js/utils/viewport.js b/js/utils/viewport.js index 68ef3cee67..fe240166d4 100644 --- a/js/utils/viewport.js +++ b/js/utils/viewport.js @@ -25,18 +25,23 @@ function viewportLoadTag() { } function viewportInitWebView() { - var hasViewportChange = false; + var initHeight = viewportProperties.height; if( ionic.Platform.isWebView() ) { - if( viewportProperties.height != 'device-height' ) { - viewportProperties.height = 'device-height'; - hasViewportChange = true; - } + viewportProperties.height = 'device-height'; + + } else if( ionic.Platform.isIOS() && viewportProperties.height ) { + // if its not a webview, and a viewport height was set, just removing + // the height value doesn't trigger the change, but setting to 0 does the trick + viewportProperties.height = '0'; + } else if( viewportProperties.height ) { delete viewportProperties.height; - hasViewportChange = true; } - if(hasViewportChange) viewportUpdate(); + + // only update the viewport tag if there was a change + if(initHeight !== viewportProperties.height) viewportUpdate(); + console.debug(viewportTag.content) } function viewportUpdate(updates) { @@ -49,7 +54,7 @@ function viewportUpdate(updates) { if(viewportProperties[key]) props.push(key + '=' + viewportProperties[key]); } - viewportTag.content = props.join(','); + viewportTag.content = props.join(', '); } ionic.DomUtil.ready(function() { diff --git a/test/unit/utils/keyboard.unit.js b/test/unit/utils/keyboard.unit.js index f419083d5a..d9c3d3dcdd 100644 --- a/test/unit/utils/keyboard.unit.js +++ b/test/unit/utils/keyboard.unit.js @@ -41,7 +41,7 @@ Tested On - Android 4.2 Cordova -iOS 7.1 Cordova with AND without viewport height DOES resize, DOES NOT fire resize event +iOS 7.1 Cordova with AND without viewport height DOES resize, DOES NOT fire resize event iOS 7.1 Safari with AND without viewport height DOES NOT resize iOS 7.0 Cordova with viewport height DOES resize, DOES fire resize event @@ -49,17 +49,17 @@ iOS 7.0 Cordova without viewport height DOES resize, DOES NOT fire resize event iOS 7.0 Safari with AND without viewport height DOES NOT resize iOS 6.1 Cordova with AND without viewport height DOES NOT resize -iOS 6.1 Safari without viewport height DOES NOT resize +iOS 6.1 Safari without viewport height DOES NOT resize -NOTES: +NOTES: -iOS 7.1 Safari with viewport height screws up ionic layout -iOS 7.0 Safari with viewport height, the scroll view does not resize properly on keyboardhide -iOS 7.0 Cordova without viewport height, scroll view does not resize properly switching inputs at bottom of page - -iOS 6.1 Cordova and Safari don't work well with viewport height + -iOS 6.1 Cordova and Safari don't work well with viewport height RECOMMENDATIONS: -iOS 7.1 Cordova no viewport height, keyboard is not over webview - -iOS 7.1 Safari no viewport height, keyboard is over webview + -iOS 7.1 Safari no viewport height, keyboard is over webview -iOS 7.0 Cordova yes viewport height, keyboard is not over webview -iOS 7.0 Safari no viewport height, keyboard is over webview @@ -215,18 +215,6 @@ describe('Ionic Keyboard', function() { expect( details.isElementUnderKeyboard ).toEqual(false); }); - it('Should not subtract the keyboard height from the contentHeight if not keyboardIsOverWebView()', function(){ - var element = document.createElement('textarea'); - var elementTop = 300; - var elementBottom = 400; - var keyboardHeight = 200; - var deviceHeight = 260; - window.innerHeight = 260; - var details = keyboardShow(element, elementTop, elementBottom, deviceHeight, keyboardHeight); - - expect( details.contentHeight ).toEqual(260); - }); - it('Should subtract the keyboard height from the contentHeight if keyboardIsOverWebView()', function(){ ionic.Platform.setPlatform('iOS'); ionic.Platform.setVersion('7.1'); diff --git a/test/unit/utils/viewport.unit.js b/test/unit/utils/viewport.unit.js index 3dd2902982..d0257455fd 100644 --- a/test/unit/utils/viewport.unit.js +++ b/test/unit/utils/viewport.unit.js @@ -12,10 +12,12 @@ iOS 6.1 Safari without viewport height DOES NOT resize NOTES: - -iOS 7.1 Safari with viewport height screws up ionic layout - -iOS 7.0 Safari with viewport height, the scroll view does not resize properly on keyboardhide - -iOS 7.0 Cordova without viewport height, scroll view does not resize properly switching inputs at bottom of page - -iOS 6.1 Cordova and Safari don't work well with viewport height + - iOS 7.1 Safari with viewport height screws up ionic layout + - iOS 7.0 Safari with viewport height, the scroll view does not resize properly on keyboardhide + - iOS 7.0 Cordova without viewport height, scroll view does not resize properly switching inputs at bottom of page + - iOS 6.1 Cordova and Safari don't work well with viewport height + - If its not a webview, and a viewport height was set, just removing + the height value doesn't trigger the change, but setting height=0 does the trick RECOMMENDATIONS: -iOS 7.1 Cordova no viewport height, keyboard is not over webview @@ -122,4 +124,14 @@ describe('Ionic Viewport', function() { expect( vportTag.content ).toEqual(originalViewport); }); + it('Should set height=0 if browser and height=device-height was already in', function(){ + ionic.Platform.setPlatform('ios'); + var originalViewport = 'initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width, height=device-height'; + vportTag.setAttribute('content', originalViewport); + viewportLoadTag(); + + // if it was changed the spaces would have been removed + expect( vportTag.content ).toEqual('initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width, height=0'); + }); + }); From 708fc85bf5c5548ea24b547990324add703fb74c Mon Sep 17 00:00:00 2001 From: Tim Lancina Date: Wed, 30 Apr 2014 16:28:44 -0500 Subject: [PATCH 06/10] keyboard size in Safari, remove isOverWebView() --- js/utils/keyboard.js | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/js/utils/keyboard.js b/js/utils/keyboard.js index 26eee24fed..43c629a66b 100644 --- a/js/utils/keyboard.js +++ b/js/utils/keyboard.js @@ -216,6 +216,10 @@ function keyboardGetHeight() { return 206; } + if (!ionic.Platform.isWebView()){ + return 216; + } + return 260; } @@ -233,27 +237,6 @@ function keyboardIsWithinScroll(ele) { return false; } -function keyboardIsOverWebView() { - if (ionic.Platform.isIOS()){ - if ( ionic.Platform.isWebView() ){ - //6.1 is over webview - return (ionic.Platform.version() < 7.0); - } - else { - //safari is always over webview - return true; - } - } - - if ( ionic.Platform.isAndroid() && ionic.Platform.isWebView() ){ - return ionic.Platform.isFullScreen; - } - - return false; - - -} - function keyboardHasPlugin() { return !!(window.cordova && cordova.plugins && cordova.plugins.Keyboard); } From 2094d83c778049610be8575f5157338e774e7fd3 Mon Sep 17 00:00:00 2001 From: Tim Lancina Date: Wed, 30 Apr 2014 16:29:28 -0500 Subject: [PATCH 07/10] keyboardGetHeight tests --- test/unit/utils/keyboard.unit.js | 128 +++++++++++++++---------------- 1 file changed, 61 insertions(+), 67 deletions(-) diff --git a/test/unit/utils/keyboard.unit.js b/test/unit/utils/keyboard.unit.js index d9c3d3dcdd..b4b28eee03 100644 --- a/test/unit/utils/keyboard.unit.js +++ b/test/unit/utils/keyboard.unit.js @@ -90,6 +90,9 @@ describe('Ionic Keyboard', function() { ionic.Platform.setPlatform(''); ionic.Platform.setVersion(''); ionic.keyboard.isOpen = false; + ionic.keyboard.height = null; + ionic.Platform.isFullScreen = false; + ionic.keyboard.landscape = false; })); afterEach(function(){ @@ -107,58 +110,6 @@ describe('Ionic Keyboard', function() { expect( details.keyboardHeight ).toEqual(200); }); - it('Should keyboardIsOverWebView()=false if Android and not isWebView', function(){ - // Android browser places the keyboard on top of the content and doesn't resize the window - ionic.Platform.setPlatform('Android'); - expect( ionic.Platform.isAndroid() ).toEqual(true); - expect( ionic.Platform.isWebView() ).toEqual(false); - - expect( ionic.Platform.isIOS() ).toEqual(false); - - expect( keyboardIsOverWebView() ).toEqual(false); - }); - - it('Should keyboardIsOverWebView()=true if Android and isWebView and isFullScreen', function(){ - // Android webview gets shrunk by cordova and the keyboard fills the gap - ionic.Platform.setPlatform('Android'); - window.cordova = {}; - expect( ionic.Platform.isAndroid() ).toEqual(true); - expect( ionic.Platform.isWebView() ).toEqual(true); - - ionic.Platform.isFullScreen = true; - - expect( keyboardIsOverWebView() ).toEqual(true); - }); - - it('Should keyboardIsOverWebView()=false if Android and isWebView and not isFullScreen', function(){ - // Android webview gets shrunk by cordova and the keyboard fills the gap - ionic.Platform.setPlatform('Android'); - window.cordova = {}; - expect( ionic.Platform.isAndroid() ).toEqual(true); - expect( ionic.Platform.isWebView() ).toEqual(true); - ionic.Platform.isFullScreen = false; - - expect( keyboardIsOverWebView() ).toEqual(false); - }); - - it('Should keyboardIsOverWebView()=true if iOS 7.0 or greater', function(){ - ionic.Platform.setPlatform('iOS'); - ionic.Platform.setVersion('7.0'); - expect( ionic.Platform.isAndroid() ).toEqual(false); - expect( ionic.Platform.isIOS() ).toEqual(true); - - expect( keyboardIsOverWebView() ).toEqual(true); - }); - - it('Should keyboardIsOverWebView()=true if less than iOS 7.0', function(){ - ionic.Platform.setPlatform('iOS'); - ionic.Platform.setVersion('6.0'); - expect( ionic.Platform.isAndroid() ).toEqual(false); - expect( ionic.Platform.isIOS() ).toEqual(true); - - expect( keyboardIsOverWebView() ).toEqual(true); - }); - it('Should keyboardHasPlugin', function() { expect( keyboardHasPlugin() ).toEqual(false); @@ -172,10 +123,67 @@ describe('Ionic Keyboard', function() { expect( keyboardHasPlugin() ).toEqual(true); }); - it('keyboardGetHeight() should = DEFAULT_KEYBOARD_HEIGHT if no plugin or resized view', function(){ + it('keyboardGetHeight() should use the keyboard plugin if it is available', function(){ + ionic.keyboard.height = 216; + expect( keyboardGetHeight() ).toEqual(216); + }); + + it('keyboardGetHeight() should = 275 if Cordova Android and is fullscreen', function(){ + ionic.Platform.setPlatform('android'); + window.cordova = {}; + ionic.Platform.isFullScreen = true; + expect( keyboardGetHeight() ).toEqual(275); }); + it('keyboardGetHeight() should = (keyboardViewportHeight - window.innerHeight) if Android and not fullscreen', function(){ + ionic.Platform.setPlatform('android'); + expect( ionic.Platform.isFullScreen ).toEqual(false); + + keyboardViewportHeight = 480; + window.innerHeight = 280 + + expect( keyboardGetHeight() ).toEqual(200); + }); + + it('keyboardGetHeight() should = 0 if keyboardViewportHeight = window.innerHeight and Android and not fullscreen', function(){ + ionic.Platform.setPlatform('android'); + expect( ionic.Platform.isFullScreen ).toEqual(false); + + keyboardViewportHeight = 480; + window.innerHeight = 480; + + expect( keyboardGetHeight() ).toEqual(0); + }); + + it('keyboardGetHeight() should = 206 if iOS and in landscape orientation', function(){ + ionic.Platform.setPlatform('iOS'); + ionic.keyboard.landscape = true; + + expect( keyboardGetHeight() ).toEqual(206); + }) + + it('keyboardGetHeight() should = 216 if iOS Safari', function(){ + ionic.Platform.setPlatform('iOS'); + + expect( ionic.Platform.isWebView() ).toEqual(false); + expect( keyboardGetHeight() ).toEqual(216); + }) + + it('keyboardGetHeight() should = 260 if iOS Cordova', function(){ + ionic.Platform.setPlatform('iOS'); + window.cordova = {}; + + expect( ionic.Platform.isWebView() ).toEqual(true); + expect( keyboardGetHeight() ).toEqual(260); + }) + + it('keyboardGetHeight() should = 275 if not Android or iOS', function(){ + ionic.Platform.setPlatform('WP8'); + + expect( keyboardGetHeight() ).toEqual(275); + }) + it('keyboardUpdateViewportHeight() should update when window.innerHeight > keyboardViewportHeight', function(){ window.innerHeight = 460; keyboardViewportHeight = 320; @@ -215,18 +223,4 @@ describe('Ionic Keyboard', function() { expect( details.isElementUnderKeyboard ).toEqual(false); }); - it('Should subtract the keyboard height from the contentHeight if keyboardIsOverWebView()', function(){ - ionic.Platform.setPlatform('iOS'); - ionic.Platform.setVersion('7.1'); - - var element = document.createElement('textarea'); - var elementTop = 300; - var elementBottom = 400; - var keyboardHeight = 200; - var deviceHeight = 568; - var details = keyboardShow(element, elementTop, elementBottom, deviceHeight, keyboardHeight); - - expect( details.contentHeight ).toEqual(368); - }); - }); From 5f8e9040bd8eb8dfef0db5bfef9275ef4a51f0da Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 2 May 2014 10:12:48 -0500 Subject: [PATCH 08/10] fix(viewport): Auto update viewport tag --- js/utils/platform.js | 9 +- js/utils/viewport.js | 102 ++++- scss/_platform.scss | 8 +- test/html/viewState.html | 36 ++ test/unit/angular/service/platform.unit.js | 41 +- test/unit/utils/viewport.unit.js | 449 +++++++++++++++++++-- test/unit/views/scrollView.unit.js | 5 +- 7 files changed, 583 insertions(+), 67 deletions(-) diff --git a/js/utils/platform.js b/js/utils/platform.js index 129cdbc1a7..5af319faef 100644 --- a/js/utils/platform.js +++ b/js/utils/platform.js @@ -90,6 +90,8 @@ if(this.isWebView()) { this.platforms.push('webview'); this.platforms.push('cordova'); + } else { + this.platforms.push('browser'); } if(this.isIPad()) this.platforms.push('ipad'); @@ -129,7 +131,10 @@ * @returns {boolean} Whether we are running on iPad. */ isIPad: function() { - return this.ua.toLowerCase().indexOf('ipad') >= 0; + if( /iPad/i.test(window.navigator.platform) ) { + return true; + } + return /iPad/i.test(this.ua); }, /** * @ngdoc method @@ -170,7 +175,7 @@ } else if(this.ua.indexOf('iPhone') > -1 || this.ua.indexOf('iPad') > -1 || this.ua.indexOf('iPod') > -1) { platformName = 'ios'; } else { - platformName = ''; + platformName = window.navigator.platform && window.navigator.platform.toLowerCase().split(' ')[0] || ''; } }, diff --git a/js/utils/viewport.js b/js/utils/viewport.js index fe240166d4..3f62d4d21b 100644 --- a/js/utils/viewport.js +++ b/js/utils/viewport.js @@ -2,6 +2,14 @@ var viewportTag; var viewportProperties = {}; +ionic.viewport = { + orientation: function() { + // 0 = Portrait + // 90 = Landscape + // not using window.orientation because each device has a different implementation + return (window.innerWidth > window.innerHeight ? 90 : 0); + } +}; function viewportLoadTag() { var x; @@ -20,38 +28,96 @@ function viewportLoadTag() { keyValue = props[x].split('='); if(keyValue.length == 2) viewportProperties[ keyValue[0] ] = keyValue[1]; } - viewportInitWebView(); + viewportUpdate(); } } -function viewportInitWebView() { +function viewportUpdate() { + // unit tests in viewport.unit.js + + var initWidth = viewportProperties.width; var initHeight = viewportProperties.height; + var p = ionic.Platform; + var version = p.version(); + var DEVICE_WIDTH = 'device-width'; + var DEVICE_HEIGHT = 'device-height'; + var orientation = ionic.viewport.orientation(); - if( ionic.Platform.isWebView() ) { - viewportProperties.height = 'device-height'; + // Most times we're removing the height and adding the width + // So this is the default to start with, then modify per platform/version/oreintation + delete viewportProperties.height; + viewportProperties.width = DEVICE_WIDTH; - } else if( ionic.Platform.isIOS() && viewportProperties.height ) { - // if its not a webview, and a viewport height was set, just removing - // the height value doesn't trigger the change, but setting to 0 does the trick - viewportProperties.height = '0'; + if( p.isIPad() ) { + // iPad + + if( version > 7 ) { + // iPad >= 7.1 + // https://issues.apache.org/jira/browse/CB-4323 + delete viewportProperties.width; + + } else { + // iPad <= 7.0 + + if( p.isWebView() ) { + // iPad <= 7.0 WebView + + if( orientation == 90 ) { + // iPad <= 7.0 WebView Landscape + viewportProperties.height = '0'; + + } else if(version == 7) { + // iPad <= 7.0 WebView Portait + viewportProperties.height = DEVICE_HEIGHT; + } + } else { + // iPad <= 6.1 Browser + if(version < 7) { + viewportProperties.height = '0'; + } + } + } + + } else if( p.isIOS() ) { + // iPhone + + if( p.isWebView() ) { + // iPhone WebView + + if(version > 7) { + // iPhone >= 7.1 WebView + delete viewportProperties.width; + + } else if(version < 7) { + // iPhone <= 6.1 WebView + // if height was set it needs to get removed with this hack for <= 6.1 + if( initHeight ) viewportProperties.height = '0'; + } + + } else { + // iPhone Browser + + if (version < 7) { + // iPhone <= 6.1 Browser + // if height was set it needs to get removed with this hack for <= 6.1 + if( initHeight ) viewportProperties.height = '0'; + } + } - } else if( viewportProperties.height ) { - delete viewportProperties.height; } // only update the viewport tag if there was a change - if(initHeight !== viewportProperties.height) viewportUpdate(); - console.debug(viewportTag.content) + if(initWidth !== viewportProperties.width || initHeight !== viewportProperties.height) { + viewportTagUpdate(); + } } -function viewportUpdate(updates) { - if(!viewportTag) return; - +function viewportTagUpdate(updates) { ionic.Utils.extend(viewportProperties, updates); var key, props = []; for(key in viewportProperties) { - if(viewportProperties[key]) props.push(key + '=' + viewportProperties[key]); + if( viewportProperties[key] ) props.push(key + '=' + viewportProperties[key]); } viewportTag.content = props.join(', '); @@ -59,4 +125,8 @@ function viewportUpdate(updates) { ionic.DomUtil.ready(function() { viewportLoadTag(); + + window.addEventListener("orientationchange", function(){ + setTimeout(viewportUpdate, 1000); + }, false); }); diff --git a/scss/_platform.scss b/scss/_platform.scss index e8460a0e8c..ece4c7376d 100644 --- a/scss/_platform.scss +++ b/scss/_platform.scss @@ -26,7 +26,7 @@ top: $bar-height + $ios7-statusbar-height; } - .has-header, + .has-header, .bar-subheader { top: $bar-height + $ios7-statusbar-height; } @@ -45,3 +45,9 @@ margin-bottom: 20px; } } + +@media (orientation:landscape) { + .platform-ios7.platform-browser.platform-ipad { + position: fixed; // required for iPad 7 Safari + } +} diff --git a/test/html/viewState.html b/test/html/viewState.html index 711b31456e..a641667b8b 100644 --- a/test/html/viewState.html +++ b/test/html/viewState.html @@ -258,6 +258,42 @@ + + + + + + + + + + + +
diff --git a/test/unit/angular/service/platform.unit.js b/test/unit/angular/service/platform.unit.js index 407cc69f2a..762bcb9bd0 100644 --- a/test/unit/angular/service/platform.unit.js +++ b/test/unit/angular/service/platform.unit.js @@ -5,6 +5,9 @@ describe('Ionic Platform Service', function() { beforeEach(inject(function($window, $ionicPlatform, $rootScope) { window = $window; + window.navigator = { + platform: '' + }; ionic.Platform.ua = ''; ionicPlatform = $ionicPlatform; rootScope = $rootScope; @@ -84,6 +87,39 @@ describe('Ionic Platform Service', function() { expect(ionic.Platform.version()).toEqual(7.0); }); + it('should not be iPad from none iPad user agent', function() { + ionic.Platform.ua = 'Mozilla/5.0 (iPhone; CPU OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B554a Safari/9537.53'; + ionic.Platform.setPlatform(undefined); + ionic.Platform.setVersion(undefined); + expect(ionic.Platform.isIPad()).toEqual(false); + }); + + it('should be iPad from user agent', function() { + ionic.Platform.ua = 'Mozilla/5.0 (iPad; CPU OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B554a Safari/9537.53'; + ionic.Platform.setPlatform(undefined); + ionic.Platform.setVersion(undefined); + expect(ionic.Platform.isIPad()).toEqual(true); + }); + + it('should be iPad from iPad in window.navigator.platform and webview, but iPhone in user agent', function() { + window.cordova = {}; + ionic.Platform.ua = 'Mozilla/5.0 (iPhone; CPU iPhone OS 6_1 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25'; + window.navigator = { + platform: 'iPad Simulator' + }; + ionic.Platform.setPlatform(undefined); + ionic.Platform.setVersion(undefined); + expect(ionic.Platform.isIPad()).toEqual(true); + }); + + it('should not be iPad from no in window.navigator.platform, and iPhone in user agent', function() { + ionic.Platform.ua = 'Mozilla/5.0 (iPhone; CPU iPhone OS 6_1 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25'; + window.navigator = {}; + ionic.Platform.setPlatform(undefined); + ionic.Platform.setVersion(undefined); + expect(ionic.Platform.isIPad()).toEqual(false); + }); + it('is iOS', function() { ionic.Platform.setPlatform('iOS'); expect(ionic.Platform.isIOS()).toEqual(true); @@ -104,6 +140,7 @@ describe('Ionic Platform Service', function() { }); it('is WebView', function() { + window.cordova = undefined; expect(ionic.Platform.isWebView()).toEqual(false); window.cordova = {}; expect(ionic.Platform.isWebView()).toEqual(true); @@ -155,7 +192,7 @@ describe('Ionic Platform Service', function() { expect(ionic.Platform.platforms[1]).toEqual('cordova'); }); - it('should not set any platform', function() { + it('should not set if its not a webview but only a browser', function() { window.cordova = null; window.PhoneGap = null; window.phonegap = null; @@ -164,7 +201,7 @@ describe('Ionic Platform Service', function() { ionic.Platform._checkPlatforms() - expect(ionic.Platform.platforms.length).toEqual(0); + expect(ionic.Platform.platforms[0]).toEqual('browser'); }); it('sets grade a from iOS7', function() { diff --git a/test/unit/utils/viewport.unit.js b/test/unit/utils/viewport.unit.js index d0257455fd..ff1b417cfc 100644 --- a/test/unit/utils/viewport.unit.js +++ b/test/unit/utils/viewport.unit.js @@ -29,6 +29,9 @@ -iOS 6.1 Cordova no viewport height, keyboard is over webview -iOS 6.1 Safari no viewport height, keyboard is over webview + http://cordova.apache.org/docs/en/3.3.0/guide_platforms_ios_upgrading.md.html#Upgrading%20iOS + https://issues.apache.org/jira/browse/CB-4323 + */ @@ -42,6 +45,9 @@ describe('Ionic Viewport', function() { _activeElement = null; // the element which has focus window.cordova = undefined; window.device = undefined; + window.navigator = {}; + window.innerWidth = 1; + window.innerHeight = 2; ionic.Platform.ua = ''; ionic.Platform.platforms = null; ionic.Platform.setPlatform(''); @@ -59,79 +65,434 @@ describe('Ionic Viewport', function() { if(vportTag) vportTag.parentNode.removeChild(vportTag); }); - it('Should have height=device-height for iOS 7+ on webview', function(){ + + + // iOS 7.1, iPad, WebView + + it('Should remove width and height from viewport for iOS >= 7.1, iPad, WebView', function(){ + ionic.Platform.setPlatform('ios'); + ionic.Platform.ua = 'ipad'; + ionic.Platform.setVersion('7.1'); + window.cordova = {}; + + vportTag.content = 'user-scalable=no, width=device-width, height=device-height'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no'); + }); + + + // iOS 7.1, iPad, Browser + + it('Should remove width and height from viewport for iOS >= 7.1, iPad, Browser', function(){ + ionic.Platform.setPlatform('ios'); + ionic.Platform.ua = 'ipad'; + ionic.Platform.setVersion('7.1'); + + vportTag.content = 'user-scalable=no, width=device-width, height=device-height'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no'); + }); + + + // iOS 7.0, iPad, WebView + + it('Should keep width and height in viewport for iOS 7.0, iPad, WebView, Portrait', function(){ + ionic.Platform.setPlatform('ios'); + ionic.Platform.ua = 'ipad'; + ionic.Platform.setVersion('7.0'); + window.cordova = {}; + window.innerWidth = 1; + window.innerHeight = 2; + + vportTag.content = 'user-scalable=no, width=device-width, height=device-height'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width, height=device-height'); + }); + + it('Should add width and height to viewport for iOS 7.0, iPad, WebView, Portrait', function(){ + ionic.Platform.setPlatform('ios'); + ionic.Platform.ua = 'ipad'; + ionic.Platform.setVersion('7.0'); + window.cordova = {}; + window.innerWidth = 1; + window.innerHeight = 2; + + vportTag.content = 'user-scalable=no'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width, height=device-height'); + }); + + it('Should add width and height=0 to viewport for iOS 7.0, iPad, WebView, Landscape', function(){ + ionic.Platform.setPlatform('ios'); + ionic.Platform.ua = 'ipad'; + ionic.Platform.setVersion('7.0'); + window.cordova = {}; + window.innerWidth = 2; + window.innerHeight = 1; + + vportTag.content = 'user-scalable=no'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width, height=0'); + }); + + it('Should keep width reset height to 0 in viewport for iOS 7.0, iPad, WebView, Landscape', function(){ + ionic.Platform.setPlatform('ios'); + ionic.Platform.ua = 'ipad'; + ionic.Platform.setVersion('7.0'); + window.cordova = {}; + window.innerWidth = 2; + window.innerHeight = 1; + + vportTag.content = 'user-scalable=no, width=device-width, height=device-height'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width, height=0'); + }); + + + // iOS 7.0, iPad, Browser + + it('Should keep width, but remove height from viewport for iOS 7.0, iPad, Browser', function(){ + ionic.Platform.setPlatform('ios'); + ionic.Platform.ua = 'ipad'; + ionic.Platform.setVersion('7.0'); + + vportTag.content = 'user-scalable=no, width=device-width, height=device-height'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); + }); + + it('Should add width, but not add height to viewport for iOS 7.0, iPad, Browser', function(){ + ionic.Platform.setPlatform('ios'); + ionic.Platform.ua = 'ipad'; + ionic.Platform.setVersion('7.0'); + + vportTag.content = 'user-scalable=no'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); + }); + + + // iOS 6.1, iPad, WebView + + it('Should keep width, but remove height from viewport for iOS 6.1, iPad, WebView, Portrait', function(){ + ionic.Platform.setPlatform('ios'); + ionic.Platform.ua = 'ipad'; + ionic.Platform.setVersion('6.1'); + window.cordova = {}; + window.innerWidth = 1; + window.innerHeight = 2; + + vportTag.content = 'user-scalable=no, width=device-width, height=device-height'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); + }); + + it('Should add width, but not add height to viewport for iOS 6.1, iPad, WebView, Portrait', function(){ + ionic.Platform.setPlatform('ios'); + ionic.Platform.ua = 'ipad'; + ionic.Platform.setVersion('6.1'); + window.cordova = {}; + window.innerWidth = 1; + window.innerHeight = 2; + + vportTag.content = 'user-scalable=no'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); + }); + + it('Should keep width, but replace height with 0 in viewport for iOS 6.1, iPad, WebView, Landscape', function(){ + ionic.Platform.setPlatform('ios'); + ionic.Platform.ua = 'ipad'; + ionic.Platform.setVersion('6.1'); + window.cordova = {}; + window.innerWidth = 2; + window.innerHeight = 1; + + vportTag.content = 'user-scalable=no, width=device-width, height=device-height'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width, height=0'); + }); + + it('Should add width and add height=0 to viewport for iOS 6.1, iPad, WebView, Landscape', function(){ + ionic.Platform.setPlatform('ios'); + ionic.Platform.ua = 'ipad'; + ionic.Platform.setVersion('6.1'); + window.cordova = {}; + window.innerWidth = 2; + window.innerHeight = 1; + + vportTag.content = 'user-scalable=no'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width, height=0'); + }); + + + // iOS 6.1, iPad, Browser + + it('Should keep width, and set height=0 for viewport for iOS 6.1, iPad, Browser, Portrait', function(){ + ionic.Platform.setPlatform('ios'); + ionic.Platform.ua = 'ipad'; + ionic.Platform.setVersion('6.1'); + + vportTag.content = 'user-scalable=no, width=device-width, height=device-height'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width, height=0'); + }); + + it('Should add width, and add height=0 to viewport for iOS 6.1, iPad, Browser', function(){ + ionic.Platform.setPlatform('ios'); + ionic.Platform.ua = 'ipad'; + ionic.Platform.setVersion('6.1'); + + vportTag.content = 'user-scalable=no'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width, height=0'); + }); + + + // iOS 7.1, iPhone, WebView + + it('Should remove width and height from viewport for iOS 7.1, iPhone, WebView', function(){ + ionic.Platform.setPlatform('ios'); + ionic.Platform.setVersion('7.1'); + window.cordova = {}; + + vportTag.content = 'user-scalable=no, width=device-width, height=device-height'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no'); + }); + + it('Should do nothing width and height already in viewport for iOS 7.1, iPhone, WebView', function(){ + ionic.Platform.setPlatform('ios'); + ionic.Platform.setVersion('7.1'); + window.cordova = {}; + + vportTag.content = 'user-scalable=no'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no'); + }); + + + // iOS 7.1, iPhone, Browser + + it('Should keep width, but remove height from viewport for iOS >= 7.1, iPhone, Browser', function(){ + ionic.Platform.setPlatform('iOS'); + ionic.Platform.setVersion('7.1'); + + vportTag.content = 'user-scalable=no, width=device-width, height=device-height'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); + }); + + it('Should add width, but not height to viewport for iOS >= 7.1, iPhone, Browser', function(){ + ionic.Platform.setPlatform('iOS'); + ionic.Platform.setVersion('7.1'); + + vportTag.content = 'user-scalable=no'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); + }); + + + // iOS 7.0, iPhone, WebView + + it('Should keep width, but not height in viewport for iOS 7.0, iPhone, WebView', function(){ ionic.Platform.setPlatform('iOS'); ionic.Platform.setVersion('7.0'); - expect( ionic.Platform.isAndroid() ).toEqual(false); - expect( ionic.Platform.isIOS() ).toEqual(true); - - //so isWebView() is true window.cordova = {}; + vportTag.content = 'user-scalable=no, width=device-width, height=device-height'; viewportLoadTag(); - expect( viewportProperties.height ).toEqual('device-height'); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); }); - it('Should not have height=device-height for iOS 7+ on browser', function(){ + it('Should add width, but not height to viewport for iOS 7.0, iPhone, WebView', function(){ ionic.Platform.setPlatform('iOS'); ionic.Platform.setVersion('7.0'); - expect( ionic.Platform.isAndroid() ).toEqual(false); - expect( ionic.Platform.isIOS() ).toEqual(true); - - viewportLoadTag(); - expect( viewportProperties.height ).not.toEqual('device-height'); - }); - - it('Should have height=device-height for Android on webview', function(){ - ionic.Platform.setPlatform('Android'); - expect( ionic.Platform.isAndroid() ).toEqual(true); - expect( ionic.Platform.isIOS() ).toEqual(false); - - //so isWebView() is true window.cordova = {}; + vportTag.content = 'user-scalable=no'; viewportLoadTag(); - expect( viewportProperties.height ).toEqual('device-height'); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); }); - it('Should not have height=device-height for Android on browser', function(){ - ionic.Platform.setPlatform('Android'); - expect( ionic.Platform.isAndroid() ).toEqual(true); - expect( ionic.Platform.isIOS() ).toEqual(false); + // iOS 7.0, iPhone, Browser + + it('Should keep width but remove height from viewport for iOS 7.0, iPhone, Browser', function(){ + ionic.Platform.setPlatform('iOS'); + ionic.Platform.setVersion('7.0'); + + vportTag.content = 'user-scalable=no, width=device-width, height=device-height'; viewportLoadTag(); - expect( viewportProperties.height ).not.toEqual('device-height'); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); }); - it('Should not re-add height=device-height for webview if its already there', function(){ - ionic.Platform.setPlatform('ios'); + it('Should add width but not height to viewport for iOS 7.0, iPhone, Browser', function(){ + ionic.Platform.setPlatform('iOS'); + ionic.Platform.setVersion('7.0'); + + vportTag.content = 'user-scalable=no'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); + }); + + + // iOS 6.1, iPhone, WebView + + it('Should add width but not height to viewport for iOS 6.1, iPhone, WebView', function(){ + ionic.Platform.setPlatform('iOS'); + ionic.Platform.setVersion('6.1'); window.cordova = {}; - var originalViewport = ' initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width, height=device-height '; - vportTag.setAttribute('content', originalViewport); + + vportTag.content = 'user-scalable=no'; viewportLoadTag(); - // if it was changed the spaces would have been removed - expect( vportTag.content ).toEqual(originalViewport); + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); }); - it('Should not update the viewport if its not a webview and height=device-height wasnt already in', function(){ - ionic.Platform.setPlatform('ios'); - var originalViewport = ' initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width '; - vportTag.setAttribute('content', originalViewport); + it('Should keep width but replace height=device-height with height=0 in viewport for iOS 6.1, iPhone, WebView', function(){ + ionic.Platform.setPlatform('iOS'); + ionic.Platform.setVersion('6.1'); + window.cordova = {}; + + vportTag.content = 'user-scalable=no, width=device-width, height=device-height'; viewportLoadTag(); - // if it was changed the spaces would have been removed - expect( vportTag.content ).toEqual(originalViewport); + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width, height=0'); }); - it('Should set height=0 if browser and height=device-height was already in', function(){ - ionic.Platform.setPlatform('ios'); - var originalViewport = 'initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width, height=device-height'; - vportTag.setAttribute('content', originalViewport); + + // iOS 6.1, iPhone, Browser + + it('Should add width but not height to viewport for iOS 6.1, iPhone, Browser', function(){ + ionic.Platform.setPlatform('iOS'); + ionic.Platform.setVersion('6.1'); + + vportTag.content = 'user-scalable=no'; viewportLoadTag(); - // if it was changed the spaces would have been removed - expect( vportTag.content ).toEqual('initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width, height=0'); + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); + }); + + it('Should keep width but remove height from viewport for iOS 6.1, iPhone, Browser', function(){ + ionic.Platform.setPlatform('iOS'); + ionic.Platform.setVersion('6.1'); + + vportTag.content = 'user-scalable=no, width=device-width, height=device-height'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width, height=0'); + }); + + + // Android 4.4, WebView + + it('Should add width, but not height to viewport for Android 4.4, WebView', function(){ + ionic.Platform.setPlatform('android'); + ionic.Platform.setVersion('4.4'); + window.cordova = {}; + + vportTag.content = 'user-scalable=no'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); + }); + + it('Should keep width, but remove height from viewport for Android 4.4, WebView', function(){ + ionic.Platform.setPlatform('android'); + ionic.Platform.setVersion('4.4'); + window.cordova = {}; + + vportTag.content = 'user-scalable=no, width=device-width, height=device-height'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); + }); + + + // Android 4.4, Browser + + it('Should add width, but not height to viewport for Android 4.4, Browser', function(){ + ionic.Platform.setPlatform('android'); + ionic.Platform.setVersion('4.4'); + + vportTag.content = 'user-scalable=no'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); + }); + + it('Should keep width, but remove height from viewport for Android 4.4, Browser', function(){ + ionic.Platform.setPlatform('android'); + ionic.Platform.setVersion('4.4'); + + vportTag.content = 'user-scalable=no, width=device-width, height=device-height'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); + }); + + + // Standard Browser + + it('Should add width, but not height to viewport for Standard Browser', function(){ + ionic.Platform.ua = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36'; + + vportTag.content = 'user-scalable=no'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); + }); + + it('Should keep width, but remove height from viewport for Standard Browser', function(){ + ionic.Platform.setPlatform('android'); + ionic.Platform.setVersion('4.4'); + + vportTag.content = 'user-scalable=no, width=device-width, height=device-height'; + viewportLoadTag(); + + expect( vportTag.content ).toEqual('user-scalable=no, width=device-width'); + }); + + + + it('Should get portrait (0) orientation', function(){ + window.innerWidth = 768; + window.innerHeight = 1024; + expect( ionic.viewport.orientation() ).toEqual(0); + + window.innerWidth = 500; + window.innerHeight = 500; + expect( ionic.viewport.orientation() ).toEqual(0); + }); + + it('Should get landscape (90) orientation', function(){ + window.innerWidth = 1024; + window.innerHeight = 768; + expect( ionic.viewport.orientation() ).toEqual(90); }); }); diff --git a/test/unit/views/scrollView.unit.js b/test/unit/views/scrollView.unit.js index a6d77d7d3b..5c9ebd2014 100644 --- a/test/unit/views/scrollView.unit.js +++ b/test/unit/views/scrollView.unit.js @@ -37,19 +37,20 @@ describe('Scroll View', function() { it('Should resize when the keyboard is showing', function() { var element = document.createElement('textarea'); + ionic.Platform.setPlatform('ios'); s.appendChild(element); document.body.appendChild(sc); var sv = new ionic.views.Scroll({ el: sc, }); - + var scHeight = 500; sc.style.height = scHeight + "px"; sc.style.display = "block"; var keyboardHeight = 200; - details = { + details = { contentHeight: 260, elementBottom: 400, elementTop: 300, From 7cfa3a685d485bc86cf84a342a3b18e9da026e26 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 2 May 2014 10:50:02 -0500 Subject: [PATCH 09/10] fix for viewport props w/ only key, no value --- js/utils/viewport.js | 14 ++++++++------ test/unit/utils/viewport.unit.js | 12 ++++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/js/utils/viewport.js b/js/utils/viewport.js index 3f62d4d21b..806b59b5f8 100644 --- a/js/utils/viewport.js +++ b/js/utils/viewport.js @@ -25,8 +25,10 @@ function viewportLoadTag() { var props = viewportTag.content.toLowerCase().replace(/\s+/g, '').split(','); var keyValue; for(x=0; x 1 ? keyValue[1] : '_'); + } } viewportUpdate(); } @@ -112,12 +114,12 @@ function viewportUpdate() { } } -function viewportTagUpdate(updates) { - ionic.Utils.extend(viewportProperties, updates); - +function viewportTagUpdate() { var key, props = []; for(key in viewportProperties) { - if( viewportProperties[key] ) props.push(key + '=' + viewportProperties[key]); + if( viewportProperties[key] ) { + props.push(key + (viewportProperties[key] == '_' ? '' : '=' + viewportProperties[key]) ); + } } viewportTag.content = props.join(', '); diff --git a/test/unit/utils/viewport.unit.js b/test/unit/utils/viewport.unit.js index ff1b417cfc..99b272fa45 100644 --- a/test/unit/utils/viewport.unit.js +++ b/test/unit/utils/viewport.unit.js @@ -479,6 +479,18 @@ describe('Ionic Viewport', function() { + it('Should set viewport properties that have a key but without a value', function(){ + vportTag.content = ' keyonly, , ,, WIDTH=DeViCe-wIDTH , minimal-ui '; + viewportLoadTag(); + + expect( viewportProperties['keyonly'] ).toEqual('_'); + expect( viewportProperties['width'] ).toEqual('device-width'); + expect( viewportProperties['minimal-ui'] ).toEqual('_'); + + viewportTagUpdate(); + expect( vportTag.content ).toEqual('keyonly, width=device-width, minimal-ui'); + }); + it('Should get portrait (0) orientation', function(){ window.innerWidth = 768; window.innerHeight = 1024; From 3abab65351b9dfcdf62c6d5faa62587d2b6cf398 Mon Sep 17 00:00:00 2001 From: Tim Lancina Date: Fri, 2 May 2014 16:57:19 -0500 Subject: [PATCH 10/10] android fullscreen tweaks --- js/utils/keyboard.js | 7 ++++++- js/views/scrollView.js | 11 ++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/js/utils/keyboard.js b/js/utils/keyboard.js index 43c629a66b..c1a4e74bf4 100644 --- a/js/utils/keyboard.js +++ b/js/utils/keyboard.js @@ -23,12 +23,15 @@ ionic.keyboard = { function keyboardInit() { if( keyboardHasPlugin() ) { window.addEventListener('native.showkeyboard', keyboardNativeShow); + window.addEventListener('native.hidekeyboard', keyboardFocusOut); + } + else { + document.body.addEventListener('focusout', keyboardFocusOut); } document.body.addEventListener('ionic.focusin', keyboardBrowserFocusIn); document.body.addEventListener('focusin', keyboardBrowserFocusIn); - document.body.addEventListener('focusout', keyboardFocusOut); document.body.addEventListener('orientationchange', keyboardOrientationChange); document.removeEventListener('touchstart', keyboardInit); @@ -86,6 +89,8 @@ function keyboardShow(element, elementTop, elementBottom, viewportHeight, keyboa keyboardHeight: keyboardHeight }; + details.hasPlugin = keyboardHasPlugin(); + details.contentHeight = viewportHeight - keyboardHeight; console.debug('keyboardShow', keyboardHeight, details.contentHeight); diff --git a/js/views/scrollView.js b/js/views/scrollView.js index ae3caa0a40..8e31a917e7 100644 --- a/js/views/scrollView.js +++ b/js/views/scrollView.js @@ -640,6 +640,15 @@ ionic.views.Scroll = ionic.views.View.inherit({ //If the element is positioned under the keyboard... if( e.detail.isElementUnderKeyboard ) { + var delay; + // Wait on android for scroll view to resize + if ( !ionic.Platform.isFullScreen && e.detail.hasPlugin ) { + delay = 350; + } + else { + delay = 80; + } + //Put element in middle of visible screen //Wait for resize() to reset scroll position ionic.scroll.isScrolling = true; @@ -651,7 +660,7 @@ ionic.views.Scroll = ionic.views.View.inherit({ ionic.tap.cloneFocusedInput(container, self); self.scrollBy(0, scrollTop, true); self.onScroll(); - }, 80 ); + }, delay); } //Only the first scrollView parent of the element that broadcasted this event