From 7f1d5444e664ba0b3d36759d1d9748c1018757e1 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Tue, 5 May 2015 15:30:11 -0500 Subject: [PATCH] click block --- ionic/components/app/util.scss | 22 +++++++++++++++++++ ionic/components/app/z-index.scss | 13 ++++++----- ionic/components/aside/aside.scss | 6 +++--- ionic/components/modal/modal.scss | 5 ++--- ionic/components/nav/nav-base.js | 8 ++++++- ionic/ionic.js | 2 ++ ionic/util/click-block.js | 36 +++++++++++++++++++++++++++++++ ionic/util/focus.js | 8 +++---- 8 files changed, 84 insertions(+), 16 deletions(-) create mode 100644 ionic/util/click-block.js diff --git a/ionic/components/app/util.scss b/ionic/components/app/util.scss index 03ac5a4f79..6cdbb7f02d 100644 --- a/ionic/components/app/util.scss +++ b/ionic/components/app/util.scss @@ -78,3 +78,25 @@ $content-padding: 10px !default; } } + + +// Click Block +// -------------------------------------------------- +// Fill the screen to block clicks (a better pointer-events: none) for the body +// to avoid full-page reflows and paints which can cause flickers + +.click-block { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + opacity: 0; + z-index: $z-index-click-block; + @include translate3d(-9999px, 0, 0); + overflow: hidden; +} + +.click-block-active { + @include translate3d(0, 0, 0); +} diff --git a/ionic/components/app/z-index.scss b/ionic/components/app/z-index.scss index 6027994fd2..4373d39e95 100644 --- a/ionic/components/app/z-index.scss +++ b/ionic/components/app/z-index.scss @@ -3,8 +3,11 @@ // -------------------------------------------------- -$z-index-action-menu: 110; -$z-index-alert: 100; -$z-index-content: 1; -$z-index-list-border: 50; -$z-index-toolbar-border: 20; +$z-index-content: 1 !default; +$z-index-toolbar-border: 20 !default; +$z-index-list-border: 50 !default; +$z-index-aside-overlay: 80 !default; +$z-index-modal: 100 !default; +$z-index-alert: 110 !default; +$z-index-action-menu: 120 !default; +$z-index-click-block: 9999 !default; diff --git a/ionic/components/aside/aside.scss b/ionic/components/aside/aside.scss index 7c36d574e7..60d3ea3948 100644 --- a/ionic/components/aside/aside.scss +++ b/ionic/components/aside/aside.scss @@ -9,14 +9,14 @@ $aside-transition: 0.3s linear transform; background: #eee; &[type=overlay] { - z-index: 10; + z-index: $z-index-aside-overlay; } transition: $aside-transition; &:not(.open):not(.changing) { display: none; } - + &[side=left] { width: $aside-width; left: -$aside-width; @@ -46,7 +46,7 @@ $aside-transition: 0.3s linear transform; top: -$aside-width; left: 0; right: 0; - + transform: translate3d(0,0,0); &.open, &[type=reveal] { diff --git a/ionic/components/modal/modal.scss b/ionic/components/modal/modal.scss index 626e1756f5..148cc03d02 100644 --- a/ionic/components/modal/modal.scss +++ b/ionic/components/modal/modal.scss @@ -1,4 +1,3 @@ -$modal-z-index: 10 !default; $modal-bg-color: #fff !default; $modal-backdrop-bg-active: #000 !default; @@ -27,7 +26,7 @@ $tabs-height: 40; position: fixed; top: 0; left: 0; - z-index: $modal-z-index; + z-index: $z-index-modal; width: 100%; height: 100%; } @@ -40,7 +39,7 @@ modal { display: block; position: absolute; top: 0; - z-index: $modal-z-index; + z-index: $z-index-modal; overflow: hidden; min-height: 100%; width: 100%; diff --git a/ionic/components/nav/nav-base.js b/ionic/components/nav/nav-base.js index 20b2e67a38..682b147187 100644 --- a/ionic/components/nav/nav-base.js +++ b/ionic/components/nav/nav-base.js @@ -1,6 +1,6 @@ import {NgElement} from 'angular2/angular2'; import * as util from 'ionic/util'; -import {Transition} from 'ionic/ionic'; +import {Transition, ClickBlock} from 'ionic/ionic'; const STAGED_STATE = 'staged'; @@ -150,6 +150,9 @@ export class NavBase { let resolve; let promise = new Promise(res => { resolve = res; }); + // block possible clicks during transition + ClickBlock(opts.animation !== 'none', 520); + // wait for the new item to complete setup enteringItem.setup().then(() => { @@ -184,6 +187,9 @@ export class NavBase { enteringItem.state = ACTIVE_STATE; leavingItem.state = CACHED_STATE; + // allow clicks again + ClickBlock(false); + // resolve that this push has completed resolve(); }); diff --git a/ionic/ionic.js b/ionic/ionic.js index 1c72293c6f..b0ea18c447 100644 --- a/ionic/ionic.js +++ b/ionic/ionic.js @@ -32,6 +32,8 @@ Object.defineProperties(ViewContainer.prototype, { export * from 'ionic/components' export * from 'ionic/platform/platform' export * from 'ionic/routing/router' + +export * from 'ionic/util/click-block' export * from 'ionic/util/focus' export * from 'ionic/engine/engine' diff --git a/ionic/util/click-block.js b/ionic/util/click-block.js new file mode 100644 index 0000000000..37afec0e75 --- /dev/null +++ b/ionic/util/click-block.js @@ -0,0 +1,36 @@ + +const CSS_CLICK_BLOCK = 'click-block-active'; +let cbEle, fallbackTimerId, pendingShow; + +function preventClick(ev) { + ev.preventDefault(); + ev.stopPropagation(); +} + +function show(expire) { + clearTimeout(fallbackTimerId); + fallbackTimerId = setTimeout(hide, expire || 320); + + if (cbEle) { + cbEle.classList.add(CSS_CLICK_BLOCK); + + } else { + cbEle = document.createElement('div'); + cbEle.className = 'click-block ' + CSS_CLICK_BLOCK; + document.body.appendChild(cbEle); + cbEle.addEventListener('touchstart', preventClick); + cbEle.addEventListener('mousedown', preventClick); + } +} + +function hide() { + clearTimeout(fallbackTimerId); + cbEle && cbEle.classList.remove(CSS_CLICK_BLOCK); +} + + +export let ClickBlock = function(shouldShow, expire) { + + (shouldShow ? show : hide)(expire); + +}; diff --git a/ionic/util/focus.js b/ionic/util/focus.js index 5a2bed52e0..759b17ef5d 100644 --- a/ionic/util/focus.js +++ b/ionic/util/focus.js @@ -1,4 +1,4 @@ -import {dom} from 'ionic/util' +import {raf, ready} from './dom' /* Focus Outline * -------------------------------------------------- @@ -14,7 +14,7 @@ let isKeyInputEnabled = false function keyDown(ev) { if (!isKeyInputEnabled && ev.keyCode == 9) { isKeyInputEnabled = true - dom.raf(enableKeyInput) + raf(enableKeyInput) } } @@ -34,10 +34,10 @@ function enableKeyInput() { function pointerDown() { isKeyInputEnabled = false - dom.raf(enableKeyInput) + raf(enableKeyInput) } -dom.ready().then(function() { +ready().then(function() { document.addEventListener('keydown', keyDown) })