Skip to content

Commit

Permalink
fix(item): improve open/close logic, update demos
Browse files Browse the repository at this point in the history
  • Loading branch information
manucorporat authored and adamdbradley committed Jun 12, 2016
1 parent 0660cb6 commit db9fa7e
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 130 deletions.
89 changes: 87 additions & 2 deletions demos/item-sliding/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,95 @@
import {Component} from '@angular/core';
import {ionicBootstrap} from 'ionic-angular';
import {ionicBootstrap, ItemSliding, Toast, NavController} from 'ionic-angular';


@Component({
templateUrl: 'main.html'
})
class ApiDemoApp {}
class InitialPage {
chats: any[];
logins: any[];

constructor(private nav: NavController) {
this.chats = [
{
img: './avatar-cher.png',
name: 'Cher',
message: 'Ugh. As if.',
time: '9:38 pm'
}, {
img: './avatar-dionne.png',
name: 'Dionne',
message: 'Mr. Hall was way harsh.',
time: '8:59 pm'
}, {
img: './avatar-murray.png',
name: 'Murray',
message: 'Excuse me, "Ms. Dione."',
time: 'Wed'
}];

this.logins = [
{
icon: 'logo-twitter',
name: 'Twitter',
username: 'admin',
}, {
icon: 'logo-github',
name: 'GitHub',
username: 'admin37',
}, {
icon: 'logo-instagram',
name: 'Instagram',
username: 'imanadmin',
}, {
icon: 'logo-codepen',
name: 'Codepen',
username: 'administrator',
}];
}

more(item: ItemSliding) {
console.log('More');
item.close();
}

delete(item: ItemSliding) {
console.log('Delete');
item.close();
}

mute(item: ItemSliding) {
console.log('Mute');
item.close();
}

archive(item: ItemSliding) {
console.log('Archive');
item.close();
}

download(item: ItemSliding) {
item.setClass('downloading', true);
setTimeout(() => {
const toast = Toast.create({
message: 'Item was downloaded!'
});
this.nav.present(toast);
item.setClass('downloading', false);
item.close();

// Wait 2s to close toast
setTimeout(() => toast.dismiss(), 2000);
}, 1500);
}
}


@Component({
template: '<ion-nav [root]="root"></ion-nav>'
})
class ApiDemoApp {
root = InitialPage;
}

ionicBootstrap(ApiDemoApp);
149 changes: 38 additions & 111 deletions demos/item-sliding/main.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,83 +8,37 @@
Chats
</ion-list-header>

<ion-item-sliding>
<ion-item-sliding *ngFor="let chat of chats; let ref = index" [ref]="ref" #item>
<ion-item>
<ion-avatar item-left>
<img src="./avatar-cher.png">
<img [src]="chat.img">
</ion-avatar>
<h2>Cher</h2>
<p>Ugh. As if.</p>
<h2>{{chat.name}}</h2>
<p>{{chat.message}}</p>
<ion-note item-right>
9:38 pm
{{chat.time}}
</ion-note>
</ion-item>
<ion-item-options>
<button secondary>
<ion-icon name="menu"></ion-icon>
More
</button>
<button dark>
<ion-icon name="volume-off"></ion-icon>
Mute
</button>
<button danger>
<ion-icon name="trash"></ion-icon>
Delete
</button>
</ion-item-options>
</ion-item-sliding>

<ion-item-sliding>
<ion-item>
<ion-avatar item-left>
<img src="./avatar-dionne.png">
</ion-avatar>
<h2>Dionne</h2>
<p>Mr. Hall was way harsh.</p>
<ion-note item-right>
8:59 pm
</ion-note>
</ion-item>
<ion-item-options>
<button secondary>
<button secondary (click)="more(item)">
<ion-icon name="menu"></ion-icon>
More
</button>
<button dark>
<button dark (click)="mute(item)">
<ion-icon name="volume-off"></ion-icon>
Mute
</button>
<button danger>
<button danger (click)="delete(item)">
<ion-icon name="trash"></ion-icon>
Delete
</button>
</ion-item-options>
</ion-item-sliding>

<ion-item-sliding>
<ion-item>
<ion-avatar item-left>
<img src="./avatar-murray.png">
</ion-avatar>
<h2>Murray</h2>
<p>Excuse me, "Ms. Dione."</p>
<ion-note item-right>
Wed
</ion-note>
</ion-item>
<ion-item-options>
<button secondary>
<ion-icon name="menu"></ion-icon>
More
</button>
<button dark>
<ion-icon name="volume-off"></ion-icon>
Mute
</button>
<button danger>
<ion-icon name="trash"></ion-icon>
Delete
<ion-item-options side="left">
<button primary expandable (click)="archive(item)">
<ion-icon name="archive"></ion-icon>
Archive
</button>
</ion-item-options>
</ion-item-sliding>
Expand All @@ -95,66 +49,26 @@ <h2>Murray</h2>
Logins
</ion-list-header>

<ion-item-sliding>
<ion-item-sliding *ngFor="let login of logins" #item>
<ion-item>
<ion-icon name="logo-twitter" item-left></ion-icon>
<h2>Twitter</h2>
<p>admin</p>
<ion-icon [name]="login.icon" item-left></ion-icon>
<h2>{{login.name}}</h2>
<p>{{login.username}}</p>
</ion-item>
<ion-item-options>
<button>
edit
</button>
<button danger>
<ion-icon name="trash"></ion-icon>
</button>
</ion-item-options>
</ion-item-sliding>

<ion-item-sliding>
<ion-item>
<ion-icon name="logo-github" item-left></ion-icon>
<h2>GitHub</h2>
<p>admin37</p>
</ion-item>
<ion-item-options>
<button>
edit
</button>
<button danger>
<ion-icon name="trash"></ion-icon>
</button>
</ion-item-options>
</ion-item-sliding>

<ion-item-sliding>
<ion-item>
<ion-icon name="logo-instagram" item-left></ion-icon>
<h2>Instagram</h2>
<p>imanadmin</p>
</ion-item>
<ion-item-options>
<button>
edit
</button>
<ion-item-options side="left">
<button danger>
<ion-icon name="trash"></ion-icon>
</button>
</ion-item-options>
</ion-item-sliding>

<ion-item-sliding>
<ion-item>
<ion-icon name="logo-codepen" item-left dark></ion-icon>
<h2>Codepen</h2>
<p>administrator</p>
</ion-item>
<ion-item-options>
<button>
edit
<ion-item-options (ionSwipe)="download(item)">
<button dark (click)="more(item)">
<ion-icon name="volume-off"></ion-icon>
Mute
</button>
<button danger>
<ion-icon name="trash"></ion-icon>
<button light expandable (click)="download(item)">
<ion-icon name="download" class="download-hide"></ion-icon>
<div class="download-hide">Download</div>
<ion-spinner id="download-spinner"></ion-spinner>
</button>
</ion-item-options>
</ion-item-sliding>
Expand All @@ -164,6 +78,19 @@ <h2>Codepen</h2>
</ion-content>

<style>
#download-spinner {
display: none;
}

svg circle {
stroke: white;
}
.downloading #download-spinner {
display: block;
}
.downloading .download-hide {
display: none;
}
.chat-sliding-demo ion-note {
font-size: 13px;
margin-top: -8px;
Expand Down
8 changes: 4 additions & 4 deletions src/components/item/item-sliding.scss
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@ ion-item-sliding.active-slide {
}
}

// Item Swipeable Animation
// Item Expandable Animation
// --------------------------------------------------

button[swipeable] {
.button-expandable {
flex-shrink: 0;

transition-duration: 0;
Expand All @@ -105,7 +105,7 @@ ion-item-sliding.active-swipe-left {
}
}

ion-item-sliding.active-swipe-right button[swipeable] {
ion-item-sliding.active-swipe-right .button-expandable {
order: 1;

padding-left: 90%;
Expand All @@ -114,7 +114,7 @@ ion-item-sliding.active-swipe-right button[swipeable] {
transition-property: padding-left;
}

ion-item-sliding.active-swipe-left button[swipeable] {
ion-item-sliding.active-swipe-left .button-expandable {
order: -1;

padding-right: 90%;
Expand Down
28 changes: 24 additions & 4 deletions src/components/item/item-sliding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,10 +269,10 @@ export class ItemSliding {

// Check if the drag didn't clear the buttons mid-point
// and we aren't moving fast enough to swipe open
let isOnResetZone = Math.abs(this._openAmount) < Math.abs(restingPoint / 2);
let isMovingSlow = Math.abs(velocity) < 0.3;
let isDirection = (this._openAmount > 0) === (velocity > 0);
if (isOnResetZone && (isMovingSlow || isDirection)) {
let isCloseDirection = (this._openAmount > 0) === !(velocity < 0);
let isMovingFast = Math.abs(velocity) > 0.3;
let isOnCloseZone = Math.abs(this._openAmount) < Math.abs(restingPoint / 2);
if (shouldClose(isCloseDirection, isMovingFast, isOnCloseZone)) {
restingPoint = 0;
}

Expand Down Expand Up @@ -402,3 +402,23 @@ export class ItemSliding {
}

}

function shouldClose(isCloseDirection: boolean, isMovingFast: boolean, isOnCloseZone: boolean): boolean {
// The logic required to know when the sliding item should close (openAmount=0)
// depends on three booleans (isCloseDirection, isMovingFast, isOnCloseZone)
// and it ended up being too complicated to be written manually without errors
// so the truth table is attached below: (0=false, 1=true)
// isCloseDirection | isMovingFast | isOnCloseZone || shouldClose
// 0 | 0 | 0 || 0
// 0 | 0 | 1 || 1
// 0 | 1 | 0 || 0
// 0 | 1 | 1 || 0
// 1 | 0 | 0 || 0
// 1 | 0 | 1 || 1
// 1 | 1 | 0 || 1
// 1 | 1 | 1 || 1
// The resulting expression was generated by resolving the K-map (Karnaugh map):
let shouldClose = (!isMovingFast && isOnCloseZone) || (isCloseDirection && isMovingFast);
return shouldClose;
}

Loading

0 comments on commit db9fa7e

Please sign in to comment.