Skip to content
This repository was archived by the owner on Feb 17, 2024. It is now read-only.

Commit 726bc06

Browse files
committed
feat: drag-element example with rx
1 parent abd601f commit 726bc06

File tree

4 files changed

+136
-29
lines changed

4 files changed

+136
-29
lines changed

public/index.html

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,21 @@
99
<meta name="viewport" content="width=device-width, initial-scale=1">
1010

1111
<base href="/">
12-
<!-- styles -->
12+
<!--
13+
Angular Material styles
1314
<link href="/css/angular2_material.css" rel="stylesheet" type="text/css">
15+
-->
16+
17+
<link rel="stylesheet" href="http://ajax.aspnetcdn.com/ajax/bootstrap/3.3.4/css/bootstrap.min.css">
18+
<style type="text/css">
19+
html {
20+
-moz-user-select: none;
21+
-khtml-user-select: none;
22+
-webkit-user-select: none;
23+
user-select: none;
24+
}
25+
</style>
26+
1427
<!-- Angular 2 -->
1528
<script src="/lib/traceur.min.js"></script>
1629
</head>

src/app/bootstrap.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@ bootstrap(App, [
2828
// appServicesInjectables,
2929
modelInjectables,
3030
rxPipeRegistry,
31-
bind(ChangeDetection).toClass(JitChangeDetection)
31+
// bind(ChangeDetection).toClass(JitChangeDetection)
3232
]);

src/app/components/app.ts

Lines changed: 120 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/// <reference path="../../custom_typings/ng2.d.ts" />
33

44
// Angular 2
5-
import {Component, View, coreDirectives, onChange, ON_PUSH} from 'angular2/angular2';
5+
import {Directive, Component, View, coreDirectives, onChange, onDestroy, ON_PUSH, ElementRef} from 'angular2/angular2';
66
import {Observable} from 'angular2/src/facade/async';
77
import {Inject} from 'angular2/di'
88
import {RouteConfig, Router, RouterOutlet, RouterLink} from 'angular2/router';
@@ -23,23 +23,89 @@ import {GreetIntent} from '../intents/GreetIntent';
2323
import {GreetModel} from '../models/GreetModel';
2424

2525

26+
@Directive({
27+
selector: '[drag-element]',
28+
hostListeners: {
29+
// Observable plz
30+
// 'mouseup': 'onMouseup($event)',
31+
// 'mousedown': 'onMousedown($event)'
32+
// 'window:mousemove': 'onMousedown($event)'
33+
}
34+
})
35+
export class DragElement {
36+
mouseup: Rx.Observable<any>;
37+
mousemove: Rx.Observable<any>;
38+
mousedown: Rx.Observable<any>;
39+
mousedrag: Rx.Observable<any>;
40+
constructor( {domElement}: ElementRef ) {
41+
42+
this.mouseup = this.fromDOMSource('mouseup', domElement)
43+
this.mousemove = this.fromDOMSource('mousemove', window.document);
44+
this.mousedown = this.fromDOMSource('mousedown', domElement).
45+
map( event => {
46+
event.preventDefault();
47+
// calculate offsets when mouse down
48+
var {clientY, clientX} = event;
49+
return {
50+
left: clientX - domElement.getBoundingClientRect().left,
51+
top: clientY - domElement.getBoundingClientRect().top,
52+
};
53+
});
54+
55+
// Combine mouse down with mouse move until mouse up
56+
this.mousedrag = this.mousedown.
57+
selectMany( imageOffset => {
58+
return this.mousemove.map( pos => {
59+
var {clientY, clientX} = pos;
60+
var {top, left} = imageOffset;
61+
// calculate offsets from mouse down to mouse moves
62+
return {
63+
top: clientY - top,
64+
left: clientX - left
65+
};
66+
}).takeUntil(this.mouseup);
67+
});
68+
/*
69+
todo: Use requestAnimationFrame Scheduler
70+
*/
71+
this.mousedrag.subscribe( pos => {
72+
var {top, left} = pos;
73+
var {style} = domElement;
74+
// Update position
75+
// requestAnimationFrame
76+
style.top = top + 'px';
77+
style.left = left + 'px';
78+
});
79+
}
80+
81+
fromDOMSource(eventName: string, el: any): Rx.Observable<any> {
82+
return Rx.Observable.fromEventPattern(
83+
callback => el.addEventListener(eventName, callback, false),
84+
callback => el.removeEventListener(eventName, callback)
85+
);
86+
}
87+
}
88+
89+
2690
@Component({
2791
selector: 'count',
28-
lifecycle: [onChange],
92+
// lifecycle: [onChange],
2993
// changeDetection: ON_PUSH,
3094
properties: { 'counter': 'counter' }
3195
})
3296
@View({
97+
directives: [ ],
3398
template: `
3499
<div>
35100
counter {{ counter }}
36101
37-
<div>
102+
103+
<p>
38104
<button (click)="incrementCounter()">
39105
Increment Counter from Component
40106
</button>
41107
<content></content>
42-
</div>
108+
</p>
43109
44110
</div>
45111
`
@@ -53,34 +119,68 @@ export class Count {
53119
this.counterIntent.incrementCounter();
54120
}
55121

56-
onChange(value) {
57-
console.log('CHANGE Count','\n', JSON.stringify(value, null, 2));
58-
}
122+
// onChange(value) {
123+
// console.log('CHANGE Count','\n', JSON.stringify(value, null, 2));
124+
// }
59125
}
60126

61127

62128

63129
@Component({
64130
selector: 'app',
65-
lifecycle: [onChange],
66131
// changeDetection: ON_PUSH
67132
})
68133
@View({
69134
// needed in order to tell Angular's compiler what's in the template
70-
directives: [ routerDirectives, coreDirectives, Count ],
135+
directives: [ routerDirectives, coreDirectives, Count, DragElement ],
71136
template: `
137+
<style>
138+
[drag-element] {
139+
-webkit-transform: translate3d(0, 0, 0);
140+
-moz-transform: translate3d(0, 0, 0);
141+
-ms-transform: translate3d(0, 0, 0);
142+
transform: translate3d(0, 0, 0);
143+
background-image: url(https://cdn.rawgit.com/Reactive-Extensions/rx.angular.js/master/examples/draganddrop/logo.png);
144+
background-repeat: no-repeat;
145+
background-position: center;
146+
background-size: contain;
147+
height: 200px;
148+
width: 200px;
149+
color: #000000;
150+
border: 1px solid #666666;
151+
padding: 10px;
152+
position: absolute;
153+
cursor: move;
154+
}
155+
</style>
156+
157+
<header>
158+
<h1 class="title">Hello Reactive Angular 2</h1>
159+
</header>
160+
161+
<main>
162+
<count [counter]="appState | async | get('counter')">
163+
<button (click)="handleIncrement()">Increment Counter from App</button>
164+
</count>
165+
166+
<h2>
167+
Greet {{ appState | async | get('greeting') }}
168+
</h2>
169+
170+
<p>
171+
<button (^click)="toggleGreet()">Greet {{ appState | async | get('greeting') }} </button>
172+
</p>
173+
<p>
174+
<pre>appState = {{ appState | async | json }}</pre>
175+
</p>
176+
</main>
177+
178+
<footer>
179+
<div drag-element>
180+
Draggable Div
181+
</div>
182+
</footer>
72183
73-
<h1 class="title">Hello Reactive Angular 2</h1>
74-
75-
<count [counter]="appState | async | get('counter')">
76-
<button (click)="handleIncrement()">Increment Counter from App</button>
77-
</count>
78-
79-
<h2>Greet {{ appState | async | get('greeting') }}</h2>
80-
<div>
81-
<button (^click)="toggleGreet()">Greet {{ appState | async | get('greeting') }} </button>
82-
</div>
83-
<pre>appState = {{ appState | async | json }}</pre>
84184
`
85185
})
86186
export class App {
@@ -107,8 +207,4 @@ export class App {
107207
this.greetIntent.toggleGreet();
108208
}
109209

110-
onChange(value) {
111-
console.log('CHANGE App', '\n', JSON.stringify(value, null, 2));
112-
}
113-
114210
}

src/common/rxPipes.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ export class GetPipe extends Pipe {
3535
onDestroy() {}
3636
supports(val) { return true }
3737
transform(val) {
38-
// console.log('wat1', val)
39-
return function(prop) {
40-
// console.log('wat2', val, prop);
38+
return function getProp(prop) {
4139
return (val) ? val[prop] : val;
4240
}
4341
}

0 commit comments

Comments
 (0)