Skip to content
Permalink
Browse files

add animation code

  • Loading branch information...
anchetaWern committed Mar 22, 2019
1 parent 405b784 commit 3ed67f5d56df612cbfb0c6cad5524d2c8e12991f
Showing with 204 additions and 118 deletions.
  1. +62 −20 app/app.css
  2. +42 −19 app/main-page.ts
  3. +8 −6 app/main-page.xml
  4. +18 −11 app/models/todo.ts
  5. +13 −12 app/services/todos-service.ts
  6. +61 −49 app/view-models/todo-view-model.ts
  7. +0 −1 tsconfig.json
@@ -1,5 +1,5 @@
page {
background-color: #F5F5F5;
background-color: #f5f5f5;
}

button {
@@ -9,35 +9,79 @@ button {

.icon {
font-size: 30;
font-family: 'FontAwesome';
font-family: "FontAwesome";
}

.action-bar {
background-color: #F5F5F5;
background-color: #f5f5f5;
}

.title {
color: #EAD7D7;
font-size: 100;
color: #ead7d7;
font-size: 10;
horizontal-align: center;
font-family: 'HelveticaNeue-Thin';
margin-bottom: 10;
opacity: .8;
font-family: "HelveticaNeue-Thin";
margin-bottom: 50;
opacity: 0.2;
top: -20;
}

.remove-button {
color: #B76769;
color: #b76769;
}

.remove-button:pressed {
transform: scale(1.2);
}

.main {
margin: 0 10 0 10;
}

.todo {
width: 100%;
padding: 10;
background-color: white;
}

.todo-summary {
width: 100%;
padding: 10;
background-color: white;
}

.is-new {
animation-name: slide_in;
animation-duration: 0.5;
animation-timing-function: ease-in;
animation-fill-mode: forwards;
}

.is-removed {
animation-name: slide_out;
animation-duration: 0.5;
animation-timing-function: ease-in;
animation-fill-mode: forwards;
}

@keyframes slide_in {
from {
transform: translate(-300, 0);
}
to {
transform: translate(300, 0);
}
}

@keyframes slide_out {
from {
transform: translate(0, 0);
}
to {
transform: translate(700, 0);
}
}

.new-item {
font-size: 20;
background-color: white;
@@ -46,42 +90,42 @@ button {

.hr {
height: 1;
background-color: #E6E6E6;
background-color: #e6e6e6;
}

.hr-bold {
height: 2;
background-color: #E6E6E6;
background-color: #e6e6e6;
}

.summary {
font-size: 14;
color: #9A9A9A;
color: #9a9a9a;
}

.item {
margin-left: 10;
}

.circles {
color: #E6E6E6;
color: #e6e6e6;
}

.circles-completed {
color: #63C6B4;
color: #63c6b4;
}

.chevron {
color: #E6E6E6;
color: #e6e6e6;
}

.chevron-bold {
color: #737373;
}

.completed {
text-decoration: line-through;
color: #D9D9D9;
text-decoration: line-through;
opacity: 0.1;
}

.active {
@@ -105,7 +149,7 @@ button {
.padded-border {
horizontal-align: center;
margin: 0;
border-color: #F0D5D5;
border-color: #f0d5d5;
border-width: 1;
padding: 0 2 0 2;
}
@@ -114,5 +158,3 @@ button {
margin-top: 10;
background-color: white;
}


@@ -1,47 +1,70 @@
import { Page } from 'ui/page';
import * as view from 'ui/core/view';
import { EventData } from 'data/observable';
import { ObservableArray } from 'data/observable-array';
import { SegmentedBar } from 'ui/segmented-bar';
import { Page } from "ui/page";
import * as view from "ui/core/view";
import { EventData } from "data/observable";
import { ObservableArray } from "data/observable-array";
import { SegmentedBar } from "ui/segmented-bar";

import ViewModel from './view-models/todo-view-model';
import Todo from './models/todo';
import ViewModel from "./view-models/todo-view-model";
import Todo from "./models/todo";

var viewModel = new ViewModel();

let pageLoaded = (args: EventData) => {
let page = <Page>args.object;
page.bindingContext = viewModel;
}

let message = page.getViewById("header");
message.animate({
translate: { x: 1, y: 20 },
duration: 1000,
scale: { x: 3, y: 3 },
opacity: 1
});
};

let add = (args: EventData) => {
viewModel.add();
}
let todo = viewModel.add();
setTimeout(() => {
viewModel.makeOld(todo);
}, 3000);
};

let remove = (args: EventData) => {
// Just getting the todo from the binding context.
// This weird syntax is just casting objects to please the TypeScript compiler.
// Just getting the todo from the binding context.
// This weird syntax is just casting objects to please the TypeScript compiler.
var todo = <Todo>(<view.View>args.object).bindingContext;
viewModel.remove(todo);
}
};

let onSwipe = (args: GestureEventData) => {
let item = <StackLayout>args.view;

item.animate({
translate: { x: 500, y: 1 },
duration: 700
}).then(() => {
var todo = <Todo>(<view.View>args.object).bindingContext;
viewModel.remove(todo);
});
};

let check = (args: EventData) => {
var todo = <Todo>(<view.View>args.object).bindingContext;
viewModel.check(todo);
}
viewModel.makeOld(todo);
};

let toggleSelectAll = () => {
viewModel.toggleSelectAll();
}
};

let filter = (args: any) => {

// The SegmentedBar emits one event, not a separate event for each button.
// We need to find the element that was clicked by it's index
var segementedbar = <SegmentedBar>args.object;
var segmentedBarItem = segementedbar.items[args.newIndex];

viewModel.set('theFilter', segmentedBarItem.get('completed'));
}
viewModel.set("theFilter", segmentedBarItem.get("completed"));
};

export { pageLoaded, add, remove, filter, check, toggleSelectAll }
export { pageLoaded, add, remove, filter, check, toggleSelectAll, onSwipe };
@@ -2,7 +2,7 @@
xmlns:shared="shared" loaded="pageLoaded"
xmlns:x="nativescript-statusbar" backgroundSpanUnderStatusBar="true">
<StackLayout class="main" stretch="fill">
<Label text="todos" class="title" />
<Label text="todos" class="title" id="header" />
<GridLayout columns="30, *" rows="auto" class="new-item">
<label text="&#xf078;" class="{{ selectAll ? 'icon chevron chevron-bold' : 'icon chevron' }}" tap="toggleSelectAll" col="0" visibility="{{ hasItems() ? 'visible' : 'collapsed' }}" />
<TextField class="new-item" text="{{ newTodo }}" returnKeyType="done" returnPress="add" col="1"/>
@@ -12,18 +12,20 @@
<StackLayout>
<Repeater items="{{ todos | filterCompleted() }}">
<Repeater.itemTemplate>
<StackLayout>
<GridLayout columns="30, *, auto" rows="auto" class="todo">
<AbsoluteLayout swipe="onSwipe">

<GridLayout left="{{ is_new ? -300 : 0 }}" columns="30, *, auto" rows="auto" class="{{ is_new ? 'todo is-new' : (is_removed) ? 'todo is-removed' : 'todo' }}">
<label id="{{ id }}" text="{{ completed ? '&#xf058;' : '&#xf1db;' }}" class="{{ completed ? 'icon circles-completed' : 'icon circles' }}" col="0" tap="check" />
<TextField text="{{ text }}" col="1" class="{{ completed ? 'item completed' : 'item active' }}"></TextField>
<Button id="{{ id }}" text="&#xf00d;" col="2" tap="remove" ios:class="icon remove-button" android:class="icon remove-button button-android" ></Button>
<Button id="{{ id }}" text="&#xf00d;" col="2" tap="remove" ios:class="icon remove-button" android:class="icon remove-button button-android"></Button>
</GridLayout>
<StackLayout class="hr"></StackLayout>
</StackLayout>

</AbsoluteLayout>
</Repeater.itemTemplate>
</Repeater>
<StackLayout class="summary" visibility="{{ hasItems() ? 'visible' : 'collapsed' }}">
<GridLayout columns="80, *, 160" class="todo" rows="auto, auto">
<GridLayout columns="80, *, 160" class="todo-summary" rows="auto, auto">
<Label text="{{ itemsLeft() + ' items left'}}" col="0" />
<Label text="Clear Completed" col="2" tap="{{ clearCompleted }}" android:class="button" class="right" visibility="{{ hasCompletedItems() ? 'visible' : 'collapsed' }}"/>
<SegmentedBar row="1" colspan="3" class="toggles" selectedIndexChanged="filter" selectedBackgroundColor="#B76769">
@@ -1,17 +1,24 @@
import { EventData, Observable } from 'data/observable';
import { EventData, Observable } from "data/observable";

class Todo extends Observable {
text: string;
completed: boolean = false;

constructor(text: string, completed: boolean = false) {
super();
text: string;
completed: boolean = false;
is_new: boolean = true;
is_removed: boolean = false;

this.text = text;
this.completed = completed
}
constructor(
text: string,
completed: boolean = false,
is_new: boolean = true,
is_removed: boolean = false
) {
super();

this.text = text;
this.completed = completed;
this.is_new = is_new;
this.is_removed = is_removed;
}
}

export default Todo;


@@ -1,5 +1,5 @@
import Todo from '../models/todo';
import { ObservableArray } from 'data/observable-array';
import Todo from "../models/todo";
import { ObservableArray } from "data/observable-array";

// A quick and wrapper for application-settings which already behaves very much like HTML5 LocalStorage
let TodosService = {
@@ -9,18 +9,19 @@ let TodosService = {
if (value) {
let rawTodos = <Array<Todo>>JSON.parse(value);
// we need to convert these raw todos into observables
rawTodos.forEach((todo) => {
result.push(new Todo(todo.text, todo.completed));
rawTodos.forEach(todo => {
result.push(new Todo(todo.text, todo.completed, todo.is_new));
});
return result;
}
else return [];
},

} else return [];
},

set: (key: string, value: ObservableArray<Todo>) => {
let todosArray = value.filter(() => { return true });
localStorage.setItem(key, JSON.stringify(todosArray));
let todosArray = value.filter(() => {
return true;
});
localStorage.setItem(key, JSON.stringify(todosArray));
}
}
};

export default TodosService;
export default TodosService;
Oops, something went wrong.

0 comments on commit 3ed67f5

Please sign in to comment.
You can’t perform that action at this time.