diff --git a/gulpfile.js b/gulpfile.js index 78bca428f9..a94191c2d8 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -189,7 +189,7 @@ gulp.task('bundle', ['bundle.ionic'], function() { }) gulp.task('tests', function() { - return gulp.src('ionic/components/*/test/*/**/*.spec.ts') + return gulp.src('ionic/**/test/**/*.spec.ts') .pipe(tsc(tscOptions, null, tscReporter)) .pipe(babel(getBabelOptions('dist/tests'))) .pipe(rename(function(file) { @@ -307,9 +307,8 @@ gulp.task('fonts', function() { require('./scripts/snapshot/snapshot.task')(gulp, argv, buildConfig); -gulp.task('karma', function() { +gulp.task('karma', ['tests'], function() { return karma.start({ configFile: __dirname + '/scripts/karma/karma.conf.js' }) - //return karma.start({ configFile: __dirname + '/karma.conf.js' }) }); gulp.task('karma-watch', function() { diff --git a/ionic/components/app/test/app_spec.ts b/ionic/components/app/test/app.spec.ts similarity index 100% rename from ionic/components/app/test/app_spec.ts rename to ionic/components/app/test/app.spec.ts diff --git a/ionic/components/content/content.ts b/ionic/components/content/content.ts index cae63323a8..d1be5c1c3c 100644 --- a/ionic/components/content/content.ts +++ b/ionic/components/content/content.ts @@ -10,10 +10,7 @@ import {ScrollTo} from '../../animations/scroll-to'; selector: 'ion-content', properties: [ 'parallax' - ], - host: { - ['[class.scroll-padding]']: 'scrollPadding' - } + ] }) @View({ template: '
' @@ -21,8 +18,6 @@ import {ScrollTo} from '../../animations/scroll-to'; export class Content extends Ion { constructor(elementRef: ElementRef, config: IonicConfig) { super(elementRef, config); - - this.scrollPadding = config.setting('keyboardScrollAssist'); } onIonInit() { @@ -88,12 +83,4 @@ export class Content extends Ion { } } - get scrollPadding() { - return this._sp; - } - - set scrollPadding(val) { - this._sp = val; - } - } diff --git a/ionic/components/form/form.scss b/ionic/components/form/form.scss index e68dad315c..439ab9ec62 100644 --- a/ionic/components/form/form.scss +++ b/ionic/components/form/form.scss @@ -108,10 +108,6 @@ focus-holder input { z-index: 9999; } -.scroll-padding.scroll-padding .scroll-content { - padding-bottom: 1000px; -} - /*focus-holder input[tabindex="999"] { left: 0px; } diff --git a/ionic/components/app/test/sink/sink.spec.ts b/ionic/components/text-input/test/text-input.spec.ts similarity index 80% rename from ionic/components/app/test/sink/sink.spec.ts rename to ionic/components/text-input/test/text-input.spec.ts index c92f2bf092..4736d4f930 100644 --- a/ionic/components/app/test/sink/sink.spec.ts +++ b/ionic/components/text-input/test/text-input.spec.ts @@ -1,6 +1,6 @@ import {Ion} from 'ionic/ion'; -export function run() { +export function main() { it('should be true', () => { expect(true).toBe(true); }); diff --git a/ionic/components/text-input/text-input.ts b/ionic/components/text-input/text-input.ts index 9808a414d8..05eda39d4d 100644 --- a/ionic/components/text-input/text-input.ts +++ b/ionic/components/text-input/text-input.ts @@ -160,8 +160,11 @@ export class TextInput extends Ion { // this input is inside of a scroll view // find out if text input should be manually scrolled into view - let scrollToY = this.getScollToY(); - if (scrollToY === 0) { + let ele = this.elementRef.nativeElement; + let safeAreaBottom = (Platform.height() * 0.6); + + let scrollData = this.getScollData(ele.offsetTop, ele.offsetHeight, scrollView.getDimensions(), safeAreaBottom); + if (scrollData.noScroll) { // the text input is in a safe position that doesn't require // it to be scrolled into view, just set focus now return this.setFocus(); @@ -171,16 +174,13 @@ export class TextInput extends Ion { // do not allow any clicks while it's scrolling ClickBlock(true, SCROLL_INTO_VIEW_DURATION + 200); - // used to put a lot of padding on the bottom of the scroll view - scrollView.scrollPadding = true; - // temporarily move the focus to the focus holder so the browser // doesn't freak out while it's trying to get the input in place // at this point the native text input still does not have focus this.tempFocusMove(); // scroll the input into place - scrollView.scrollTo(0, scrollToY, SCROLL_INTO_VIEW_DURATION, 8).then(() => { + scrollView.scrollTo(0, scrollData.scrollTo, SCROLL_INTO_VIEW_DURATION, 8).then(() => { // the scroll view is in the correct position now // give the native text input focus this.setFocus(); @@ -196,67 +196,70 @@ export class TextInput extends Ion { } - getScollToY() { - let ele = this.elementRef.nativeElement; - let viewDimensions = this.scrollView.getDimensions(); + getScollData(inputOffsetTop, inputOffsetHeight, scrollViewDimensions, safeAreaBottom) { + // compute input's Y values relative to the body + let inputTop = (inputOffsetTop + scrollViewDimensions.top - scrollViewDimensions.scrollTop); + let inputBottom = (inputTop + inputOffsetHeight); - // get the inputs Y position relative to the scroll view - let inputOffsetTop = ele.offsetTop; + // compute the safe area which is the viewable content area when the soft keyboard is up + let safeAreaTop = (scrollViewDimensions.top - 1); + let safeAreaHeight = (safeAreaBottom - safeAreaTop); - // compute offset values relative to the body - let contentTop = viewDimensions.top; - let inputTop = inputOffsetTop + contentTop - viewDimensions.scrollTop; - let inputBottom = (inputTop + ele.offsetHeight); + let inputTopWithinSafeArea = (inputTop >= safeAreaTop && inputTop <= safeAreaBottom); + let inputBottomWithinSafeArea = (inputBottom >= safeAreaTop && inputBottom <= safeAreaBottom); + let inputBottomBelowSafeArea = (inputBottom > safeAreaBottom); + let inputFitsWithinSafeArea = (inputOffsetHeight <= safeAreaHeight); + let distanceInputBottomBelowSafeArea = (safeAreaBottom - inputBottom); - // compute the safe area which is the viewable - // content area when the soft keyboard is up - let safeTop = contentTop - 1; - let safeBottom = (Platform.height() * 0.6); + /* + Text Input Scroll To Scenarios + --------------------------------------- + 1) Input top within safe area, bottom within safe area + 2) Input top within safe area, bottom below safe area, room to scroll + 3) Input top above safe area, bottom within safe area, room to scroll + 4) Input top below safe area, no room to scroll, input smaller than safe area + 5) Input top within safe area, bottom below safe area, no room to scroll, input smaller than safe area + 6) Input top within safe area, bottom below safe area, no room to scroll, input larger than safe area + 7) Input top below safe area, no room to scroll, input larger than safe area + */ - // Text Input Scroll To Scenarios - // --------------------------------------- - // 1) Input top within safe area, bottom within safe area - // 2) Input top within safe area, bottom below safe area - // 3) Input top and bottom below safe area - // 4) Input top above safe area, bottom within safe area - // 5) Input top above safe area, bottom below safe area + if (inputTopWithinSafeArea && inputBottomWithinSafeArea) { + // Input top within safe area, bottom within safe area + // no need to scroll to a position, it's good as-is + return { noScroll: true }; + } - if (inputTop >= safeTop && inputTop <= safeBottom) { - // Input top within safe area + // looks like we'll have to do some auto-scrolling + let scrollData = { + scrollUp: 0, + scrollDown: 0, + scrollTo: inputOffsetTop, + scrollPadding: 0, + }; - if (inputBottom <= safeBottom) { - // 1) Input top within safe area, bottom within safe area - // no need to scroll to a position, it's good as-is - return 0; + if (inputTopWithinSafeArea && inputBottomBelowSafeArea) { + // Input top within safe area, bottom below safe area + let distanceInputTopIntoSafeArea = (safeAreaTop - inputTop); + let distanceInputBottomBelowSafeArea = (inputBottom - safeAreaBottom); + + if (distanceInputBottomBelowSafeArea < distanceInputTopIntoSafeArea) { + // the input's top is farther into the safe area then the bottom is out of it + // this means we can scroll it up a little bit and the top will still be + // within the safe area + scrollData.scrollUp = distanceInputTopIntoSafeArea; + + } else { + // the input's top is less below the safe area top than the + // input's bottom is below the safe area bottom. So scroll the input + // to be at the top of the safe area, knowing that the bottom will go below + scrollData.scrollUp = distanceInputTopIntoSafeArea; } - // 2) Input top within safe area, bottom below safe area - // TODO: What if the input is still taller than safe area? - return inputOffsetTop; } - if (inputTop > safeBottom) { - // 3) Input top and bottom below safe area - // TODO: What if the input is still taller than safe area? - return inputOffsetTop; - } - - if (inputTop < safeTop) { - // Input top above safe area - - if (inputBottom <= safeTop) { - // 4) Input top above safe area, bottom within safe area - // TODO: What if the input is still taller than safe area? - return inputOffsetTop; - } - - // 5) Input top above safe area, bottom below safe area - // TODO: What if the input is still taller than safe area? - return inputOffsetTop; - } // fallback for whatever reason - return inputOffsetTop; + return scrollData; } deregListeners() { diff --git a/scripts/karma/karma.conf.js b/scripts/karma/karma.conf.js index c03348a837..d05990d431 100644 --- a/scripts/karma/karma.conf.js +++ b/scripts/karma/karma.conf.js @@ -2,7 +2,7 @@ var buildConfig = require('../build/config'); module.exports = function(config) { config.set({ - //singleRun: true, + singleRun: true, basePath: '../../', frameworks: ['jasmine'],