feat(change_detection): added an example demonstrating how to use observable models
Closes #3684
This commit is contained in:
parent
cbfc9cb344
commit
52da220016
|
@ -2,6 +2,7 @@ name: examples
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=1.10.0 <2.0.0'
|
sdk: '>=1.10.0 <2.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
|
observe: '^0.13.1'
|
||||||
angular2: '^<%= packageJson.version %>'
|
angular2: '^<%= packageJson.version %>'
|
||||||
angular2_material: '^<%= packageJson.version %>'
|
angular2_material: '^<%= packageJson.version %>'
|
||||||
browser: '^0.10.0'
|
browser: '^0.10.0'
|
||||||
|
@ -29,8 +30,9 @@ transformers:
|
||||||
- web/src/key_events/index.dart
|
- web/src/key_events/index.dart
|
||||||
- web/src/sourcemap/index.dart
|
- web/src/sourcemap/index.dart
|
||||||
- web/src/todo/index.dart
|
- web/src/todo/index.dart
|
||||||
- web/src/model_driven_forms/index.dart
|
|
||||||
- web/src/order_management/index.dart
|
- web/src/order_management/index.dart
|
||||||
|
- web/src/model_driven_forms/index.dart
|
||||||
|
- web/src/observable_models/index.dart
|
||||||
- web/src/person_management/index.dart
|
- web/src/person_management/index.dart
|
||||||
- web/src/template_driven_forms/index.dart
|
- web/src/template_driven_forms/index.dart
|
||||||
# These entrypoints are disabled until cross-package urls are working (issue #2982)
|
# These entrypoints are disabled until cross-package urls are working (issue #2982)
|
||||||
|
@ -53,6 +55,7 @@ transformers:
|
||||||
- web/src/sourcemap/index.dart
|
- web/src/sourcemap/index.dart
|
||||||
- web/src/todo/index.dart
|
- web/src/todo/index.dart
|
||||||
- web/src/model_driven_forms/index.dart
|
- web/src/model_driven_forms/index.dart
|
||||||
|
- web/src/observable_models/index.dart
|
||||||
- web/src/order_management/index.dart
|
- web/src/order_management/index.dart
|
||||||
- web/src/person_management/index.dart
|
- web/src/person_management/index.dart
|
||||||
- web/src/template_driven_forms/index.dart
|
- web/src/template_driven_forms/index.dart
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
library benchmarks.src.naive_infinite_scroll.app;
|
||||||
|
|
||||||
|
import "package:angular2/src/facade/collection.dart" show List, ListWrapper;
|
||||||
|
import "package:angular2/directives.dart" show NgIf, NgFor;
|
||||||
|
import "scroll_area.dart" show ScrollAreaComponent;
|
||||||
|
import "package:angular2/angular2.dart" show Component, Directive, View, IterableDiffers, SkipSelf, Binding;
|
||||||
|
import "package:angular2/src/directives/observable_list_diff.dart" show ObservableListDiffFactory;
|
||||||
|
import 'package:observe/observe.dart' show ObservableList;
|
||||||
|
|
||||||
|
createDiffers(IterableDiffers parent) {
|
||||||
|
return IterableDiffers.create([const ObservableListDiffFactory()], parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
const binding = const Binding(IterableDiffers,
|
||||||
|
toFactory: createDiffers, deps: const [ const[IterableDiffers, const SkipSelf()]]);
|
||||||
|
|
||||||
|
@Component(
|
||||||
|
selector: "scroll-app",
|
||||||
|
bindings: const [binding]
|
||||||
|
)
|
||||||
|
@View(directives: const [ScrollAreaComponent, NgIf, NgFor], template: '''
|
||||||
|
<div>
|
||||||
|
<div style="display: flex">
|
||||||
|
<scroll-area id="testArea"></scroll-area>
|
||||||
|
</div>
|
||||||
|
<div template="ng-if scrollAreas.length > 0">
|
||||||
|
<p>Following tables are only here to add weight to the UI:</p>
|
||||||
|
<scroll-area template="ng-for #scrollArea of scrollAreas"></scroll-area>
|
||||||
|
</div>
|
||||||
|
</div>''')
|
||||||
|
class App {
|
||||||
|
List<int> scrollAreas;
|
||||||
|
App() {
|
||||||
|
var scrollAreas = [];
|
||||||
|
for (var i = 0; i < 300; i++) {
|
||||||
|
scrollAreas.add(i);
|
||||||
|
}
|
||||||
|
this.scrollAreas = new ObservableList.from(scrollAreas);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,135 @@
|
||||||
|
library benchmarks.src.naive_infinite_scroll.cells;
|
||||||
|
|
||||||
|
import "package:angular2/src/facade/collection.dart"
|
||||||
|
show List, ListWrapper, Map;
|
||||||
|
import "common.dart"
|
||||||
|
show Company, Opportunity, Offering, Account, CustomDate, STATUS_LIST;
|
||||||
|
import "package:angular2/directives.dart" show NgFor;
|
||||||
|
import "package:angular2/angular2.dart" show Component, Directive, View;
|
||||||
|
|
||||||
|
class HasStyle {
|
||||||
|
int cellWidth;
|
||||||
|
HasStyle() {}
|
||||||
|
set width(int w) {
|
||||||
|
this.cellWidth = w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Component(
|
||||||
|
selector: "company-name",
|
||||||
|
properties: const ["width: cell-width", "company"],
|
||||||
|
changeDetection: "ON_PUSH_OBSERVE"
|
||||||
|
)
|
||||||
|
@View(
|
||||||
|
directives: const [],
|
||||||
|
template: '''<div [style.width.px]="cellWidth">{{company.name}}</div>'''
|
||||||
|
)
|
||||||
|
class CompanyNameComponent extends HasStyle {
|
||||||
|
Company company;
|
||||||
|
}
|
||||||
|
@Component(
|
||||||
|
selector: "opportunity-name",
|
||||||
|
properties: const ["width: cell-width", "opportunity"],
|
||||||
|
changeDetection: "ON_PUSH_OBSERVE"
|
||||||
|
)
|
||||||
|
@View(
|
||||||
|
directives: const [],
|
||||||
|
template: '''<div [style.width.px]="cellWidth">{{opportunity.name}}</div>'''
|
||||||
|
)
|
||||||
|
class OpportunityNameComponent extends HasStyle {
|
||||||
|
Opportunity opportunity;
|
||||||
|
}
|
||||||
|
@Component(
|
||||||
|
selector: "offering-name",
|
||||||
|
properties: const ["width: cell-width", "offering"],
|
||||||
|
changeDetection: "ON_PUSH_OBSERVE"
|
||||||
|
)
|
||||||
|
@View(
|
||||||
|
directives: const [],
|
||||||
|
template: '''<div [style.width.px]="cellWidth">{{offering.name}}</div>'''
|
||||||
|
)
|
||||||
|
class OfferingNameComponent extends HasStyle {
|
||||||
|
Offering offering;
|
||||||
|
}
|
||||||
|
class Stage {
|
||||||
|
String name;
|
||||||
|
bool isDisabled;
|
||||||
|
String backgroundColor;
|
||||||
|
Function apply;
|
||||||
|
}
|
||||||
|
@Component(
|
||||||
|
selector: "stage-buttons",
|
||||||
|
properties: const ["width: cell-width", "offering"],
|
||||||
|
changeDetection: "ON_PUSH_OBSERVE"
|
||||||
|
)
|
||||||
|
@View(directives: const [NgFor], template: '''
|
||||||
|
<div [style.width.px]="cellWidth">
|
||||||
|
<button template="ng-for #stage of stages"
|
||||||
|
[disabled]="stage.isDisabled"
|
||||||
|
[style.background-color]="stage.backgroundColor"
|
||||||
|
on-click="setStage(stage)">
|
||||||
|
{{stage.name}}
|
||||||
|
</button>
|
||||||
|
</div>''')
|
||||||
|
class StageButtonsComponent extends HasStyle {
|
||||||
|
Offering _offering;
|
||||||
|
List<Stage> stages;
|
||||||
|
Offering get offering {
|
||||||
|
return this._offering;
|
||||||
|
}
|
||||||
|
set offering(Offering offering) {
|
||||||
|
this._offering = offering;
|
||||||
|
this._computeStageButtons();
|
||||||
|
}
|
||||||
|
setStage(Stage stage) {
|
||||||
|
this._offering.status = stage.name;
|
||||||
|
this._offering.name = this._offering.name + "!";
|
||||||
|
this._computeStageButtons();
|
||||||
|
}
|
||||||
|
_computeStageButtons() {
|
||||||
|
var disabled = true;
|
||||||
|
this.stages = ListWrapper.clone(STATUS_LIST.map((status) {
|
||||||
|
var isCurrent = this._offering.status == status;
|
||||||
|
var stage = new Stage();
|
||||||
|
stage.name = status;
|
||||||
|
stage.isDisabled = disabled;
|
||||||
|
stage.backgroundColor = disabled ? "#DDD" : isCurrent ? "#DDF" : "#FDD";
|
||||||
|
if (isCurrent) {
|
||||||
|
disabled = false;
|
||||||
|
}
|
||||||
|
return stage;
|
||||||
|
}).toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Component(
|
||||||
|
selector: "account-cell",
|
||||||
|
properties: const ["width: cell-width", "account"],
|
||||||
|
changeDetection: "ON_PUSH_OBSERVE"
|
||||||
|
)
|
||||||
|
@View(directives: const [], template: '''
|
||||||
|
<div [style.width.px]="cellWidth">
|
||||||
|
<a href="/account/{{account.accountId}}">
|
||||||
|
{{account.accountId}}
|
||||||
|
</a>
|
||||||
|
</div>''')
|
||||||
|
class AccountCellComponent extends HasStyle {
|
||||||
|
Account account;
|
||||||
|
}
|
||||||
|
@Component(
|
||||||
|
selector: "formatted-cell",
|
||||||
|
properties: const ["width: cell-width", "value"],
|
||||||
|
changeDetection: "ON_PUSH_OBSERVE"
|
||||||
|
)
|
||||||
|
@View(
|
||||||
|
directives: const [],
|
||||||
|
template: '''<div [style.width.px]="cellWidth">{{formattedValue}}</div>''')
|
||||||
|
class FormattedCellComponent extends HasStyle {
|
||||||
|
String formattedValue;
|
||||||
|
set value(value) {
|
||||||
|
if (value is CustomDate) {
|
||||||
|
this.formattedValue =
|
||||||
|
'''${ value . month}/${ value . day}/${ value . year}''';
|
||||||
|
} else {
|
||||||
|
this.formattedValue = value.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,241 @@
|
||||||
|
library benchmarks.src.naive_infinite_scroll.common;
|
||||||
|
|
||||||
|
import "package:angular2/src/facade/math.dart" show Math;
|
||||||
|
import "package:angular2/src/facade/collection.dart";
|
||||||
|
import 'package:observe/observe.dart';
|
||||||
|
import 'dart:collection';
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
var ITEMS = 1000;
|
||||||
|
var ITEM_HEIGHT = 40;
|
||||||
|
var VISIBLE_ITEMS = 17;
|
||||||
|
var HEIGHT = ITEMS * ITEM_HEIGHT;
|
||||||
|
var VIEW_PORT_HEIGHT = ITEM_HEIGHT * VISIBLE_ITEMS;
|
||||||
|
var COMPANY_NAME_WIDTH = 100;
|
||||||
|
var OPPORTUNITY_NAME_WIDTH = 100;
|
||||||
|
var OFFERING_NAME_WIDTH = 100;
|
||||||
|
var ACCOUNT_CELL_WIDTH = 50;
|
||||||
|
var BASE_POINTS_WIDTH = 50;
|
||||||
|
var KICKER_POINTS_WIDTH = 50;
|
||||||
|
var STAGE_BUTTONS_WIDTH = 220;
|
||||||
|
var BUNDLES_WIDTH = 120;
|
||||||
|
var DUE_DATE_WIDTH = 100;
|
||||||
|
var END_DATE_WIDTH = 100;
|
||||||
|
var AAT_STATUS_WIDTH = 100;
|
||||||
|
var ROW_WIDTH = COMPANY_NAME_WIDTH +
|
||||||
|
OPPORTUNITY_NAME_WIDTH +
|
||||||
|
OFFERING_NAME_WIDTH +
|
||||||
|
ACCOUNT_CELL_WIDTH +
|
||||||
|
BASE_POINTS_WIDTH +
|
||||||
|
KICKER_POINTS_WIDTH +
|
||||||
|
STAGE_BUTTONS_WIDTH +
|
||||||
|
BUNDLES_WIDTH +
|
||||||
|
DUE_DATE_WIDTH +
|
||||||
|
END_DATE_WIDTH +
|
||||||
|
AAT_STATUS_WIDTH;
|
||||||
|
var STATUS_LIST = ["Planned", "Pitched", "Won", "Lost"];
|
||||||
|
var AAT_STATUS_LIST = ["Active", "Passive", "Abandoned"];
|
||||||
|
// Imitate Streamy entities.
|
||||||
|
|
||||||
|
// Just a non-trivial object. Nothing fancy or correct.
|
||||||
|
class CustomDate {
|
||||||
|
num year;
|
||||||
|
num month;
|
||||||
|
num day;
|
||||||
|
CustomDate(num y, num m, num d) {
|
||||||
|
this.year = y;
|
||||||
|
this.month = m;
|
||||||
|
this.day = d;
|
||||||
|
}
|
||||||
|
CustomDate addDays(num days) {
|
||||||
|
var newDay = this.day + days;
|
||||||
|
var newMonth = this.month + Math.floor(newDay / 30);
|
||||||
|
newDay = newDay % 30;
|
||||||
|
var newYear = this.year + Math.floor(newMonth / 12);
|
||||||
|
return new CustomDate(newYear, newMonth, newDay);
|
||||||
|
}
|
||||||
|
static CustomDate now() {
|
||||||
|
return new CustomDate(2014, 1, 28);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class RawEntity extends Object
|
||||||
|
with MapMixin<String, dynamic>
|
||||||
|
implements ObservableMap<String, dynamic> {
|
||||||
|
ObservableMap _data = new ObservableMap();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<String> get keys => _data.keys;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void clear() {
|
||||||
|
_data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
operator [](String key) {
|
||||||
|
if (!key.contains('.')) {
|
||||||
|
return _data[key];
|
||||||
|
}
|
||||||
|
var pieces = key.split('.');
|
||||||
|
var last = pieces.removeLast();
|
||||||
|
var target = _resolve(pieces, this);
|
||||||
|
if (target == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return target[last];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
operator []=(String key, value) {
|
||||||
|
if (!key.contains('.')) {
|
||||||
|
_data[key] = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var pieces = key.split('.');
|
||||||
|
var last = pieces.removeLast();
|
||||||
|
var target = _resolve(pieces, this);
|
||||||
|
target[last] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
dynamic get(String name) { return this[name]; }
|
||||||
|
|
||||||
|
set(String name, dynamic value) { this[name] = value; }
|
||||||
|
|
||||||
|
@override
|
||||||
|
remove(String key) {
|
||||||
|
if (!key.contains('.')) {
|
||||||
|
return _data.remove(key);
|
||||||
|
}
|
||||||
|
var pieces = key.split('.');
|
||||||
|
var last = pieces.removeLast();
|
||||||
|
var target = _resolve(pieces, this);
|
||||||
|
return target.remove(last);
|
||||||
|
}
|
||||||
|
|
||||||
|
_resolve(List<String> pieces, start) {
|
||||||
|
var cur = start;
|
||||||
|
for (var i = 0; i < pieces.length; i++) {
|
||||||
|
cur = cur[pieces[i]];
|
||||||
|
if (cur == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<List<ChangeRecord>> get changes => _data.changes;
|
||||||
|
@override
|
||||||
|
bool get hasObservers => _data.hasObservers;
|
||||||
|
@override
|
||||||
|
bool deliverChanges() => _data.deliverChanges();
|
||||||
|
@override
|
||||||
|
notifyPropertyChange(Symbol field, Object oldValue, Object newValue) =>
|
||||||
|
_data.notifyPropertyChange(field, oldValue, newValue);
|
||||||
|
@override
|
||||||
|
void notifyChange(ChangeRecord record) {
|
||||||
|
_data.notifyChange(record);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void observed() {
|
||||||
|
_data.observed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void unobserved() {
|
||||||
|
_data.observed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Company extends RawEntity {
|
||||||
|
String get name {
|
||||||
|
return this.get("name");
|
||||||
|
}
|
||||||
|
set name(String val) {
|
||||||
|
this.set("name", val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Offering extends RawEntity {
|
||||||
|
String get name {
|
||||||
|
return this.get("name");
|
||||||
|
}
|
||||||
|
set name(String val) {
|
||||||
|
this.set("name", val);
|
||||||
|
}
|
||||||
|
Company get company {
|
||||||
|
return this.get("company");
|
||||||
|
}
|
||||||
|
set company(Company val) {
|
||||||
|
this.set("company", val);
|
||||||
|
}
|
||||||
|
Opportunity get opportunity {
|
||||||
|
return this.get("opportunity");
|
||||||
|
}
|
||||||
|
set opportunity(Opportunity val) {
|
||||||
|
this.set("opportunity", val);
|
||||||
|
}
|
||||||
|
Account get account {
|
||||||
|
return this.get("account");
|
||||||
|
}
|
||||||
|
set account(Account val) {
|
||||||
|
this.set("account", val);
|
||||||
|
}
|
||||||
|
num get basePoints {
|
||||||
|
return this.get("basePoints");
|
||||||
|
}
|
||||||
|
set basePoints(num val) {
|
||||||
|
this.set("basePoints", val);
|
||||||
|
}
|
||||||
|
num get kickerPoints {
|
||||||
|
return this.get("kickerPoints");
|
||||||
|
}
|
||||||
|
set kickerPoints(num val) {
|
||||||
|
this.set("kickerPoints", val);
|
||||||
|
}
|
||||||
|
String get status {
|
||||||
|
return this.get("status");
|
||||||
|
}
|
||||||
|
set status(String val) {
|
||||||
|
this.set("status", val);
|
||||||
|
}
|
||||||
|
String get bundles {
|
||||||
|
return this.get("bundles");
|
||||||
|
}
|
||||||
|
set bundles(String val) {
|
||||||
|
this.set("bundles", val);
|
||||||
|
}
|
||||||
|
CustomDate get dueDate {
|
||||||
|
return this.get("dueDate");
|
||||||
|
}
|
||||||
|
set dueDate(CustomDate val) {
|
||||||
|
this.set("dueDate", val);
|
||||||
|
}
|
||||||
|
CustomDate get endDate {
|
||||||
|
return this.get("endDate");
|
||||||
|
}
|
||||||
|
set endDate(CustomDate val) {
|
||||||
|
this.set("endDate", val);
|
||||||
|
}
|
||||||
|
String get aatStatus {
|
||||||
|
return this.get("aatStatus");
|
||||||
|
}
|
||||||
|
set aatStatus(String val) {
|
||||||
|
this.set("aatStatus", val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Opportunity extends RawEntity {
|
||||||
|
String get name {
|
||||||
|
return this.get("name");
|
||||||
|
}
|
||||||
|
set name(String val) {
|
||||||
|
this.set("name", val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Account extends RawEntity {
|
||||||
|
num get accountId {
|
||||||
|
return this.get("accountId");
|
||||||
|
}
|
||||||
|
set accountId(num val) {
|
||||||
|
this.set("accountId", val);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
library benchmarks.src.naive_infinite_scroll.index;
|
||||||
|
|
||||||
|
import "package:angular2/bootstrap.dart" show bootstrap;
|
||||||
|
import "app.dart" show App;
|
||||||
|
import "package:angular2/src/core/compiler/view_pool.dart"
|
||||||
|
show APP_VIEW_POOL_CAPACITY;
|
||||||
|
import "package:angular2/di.dart" show bind;
|
||||||
|
|
||||||
|
main() {
|
||||||
|
bootstrap(App, createBindings());
|
||||||
|
}
|
||||||
|
List<dynamic> createBindings() {
|
||||||
|
return [bind(APP_VIEW_POOL_CAPACITY).toValue(100000)];
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>AngularDart Scrolling Benchmark</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<scroll-app></scroll-app>
|
||||||
|
|
||||||
|
<script src="url_params_to_form.js" type="text/javascript"></script>
|
||||||
|
<script src="index.dart" type="application/dart"></script>
|
||||||
|
<script src="naive_infinite_scroll/packages/browser/dart.js" type="text/javascript"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,86 @@
|
||||||
|
library benchmarks.src.naive_infinite_scroll.random_data;
|
||||||
|
|
||||||
|
import "package:angular2/src/facade/lang.dart" show StringWrapper;
|
||||||
|
import "package:angular2/src/facade/collection.dart" show List, ListWrapper;
|
||||||
|
import "common.dart"
|
||||||
|
show
|
||||||
|
CustomDate,
|
||||||
|
Offering,
|
||||||
|
Company,
|
||||||
|
Opportunity,
|
||||||
|
Account,
|
||||||
|
STATUS_LIST,
|
||||||
|
AAT_STATUS_LIST;
|
||||||
|
|
||||||
|
List<Offering> generateOfferings(int count) {
|
||||||
|
var res = [];
|
||||||
|
for (var i = 0; i < count; i++) {
|
||||||
|
res.add(generateOffering(i));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
Offering generateOffering(int seed) {
|
||||||
|
var res = new Offering();
|
||||||
|
res.name = generateName(seed++);
|
||||||
|
res.company = generateCompany(seed++);
|
||||||
|
res.opportunity = generateOpportunity(seed++);
|
||||||
|
res.account = generateAccount(seed++);
|
||||||
|
res.basePoints = seed % 10;
|
||||||
|
res.kickerPoints = seed % 4;
|
||||||
|
res.status = STATUS_LIST[seed % STATUS_LIST.length];
|
||||||
|
res.bundles = randomString(seed++);
|
||||||
|
res.dueDate = randomDate(seed++);
|
||||||
|
res.endDate = randomDate(seed++, res.dueDate);
|
||||||
|
res.aatStatus = AAT_STATUS_LIST[seed % AAT_STATUS_LIST.length];
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
Company generateCompany(int seed) {
|
||||||
|
var res = new Company();
|
||||||
|
res.name = generateName(seed);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
Opportunity generateOpportunity(int seed) {
|
||||||
|
var res = new Opportunity();
|
||||||
|
res.name = generateName(seed);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
Account generateAccount(int seed) {
|
||||||
|
var res = new Account();
|
||||||
|
res.accountId = seed;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
var names = [
|
||||||
|
"Foo",
|
||||||
|
"Bar",
|
||||||
|
"Baz",
|
||||||
|
"Qux",
|
||||||
|
"Quux",
|
||||||
|
"Garply",
|
||||||
|
"Waldo",
|
||||||
|
"Fred",
|
||||||
|
"Plugh",
|
||||||
|
"Xyzzy",
|
||||||
|
"Thud",
|
||||||
|
"Cruft",
|
||||||
|
"Stuff"
|
||||||
|
];
|
||||||
|
String generateName(int seed) {
|
||||||
|
return names[seed % names.length];
|
||||||
|
}
|
||||||
|
var offsets = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||||
|
CustomDate randomDate(int seed, [CustomDate minDate = null]) {
|
||||||
|
if (minDate == null) {
|
||||||
|
minDate = CustomDate.now();
|
||||||
|
}
|
||||||
|
return minDate.addDays(offsets[seed % offsets.length]);
|
||||||
|
}
|
||||||
|
var stringLengths = [5, 7, 9, 11, 13];
|
||||||
|
var charCodeOffsets = [0, 1, 2, 3, 4, 5, 6, 7, 8];
|
||||||
|
String randomString(int seed) {
|
||||||
|
var len = stringLengths[seed % 5];
|
||||||
|
var str = "";
|
||||||
|
for (var i = 0; i < len; i++) {
|
||||||
|
str += StringWrapper.fromCharCode(97 + charCodeOffsets[seed % 9] + i);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
library benchmarks.src.naive_infinite_scroll.scroll_area;
|
||||||
|
|
||||||
|
import "package:angular2/src/facade/collection.dart" show ListWrapper;
|
||||||
|
import "package:angular2/src/facade/math.dart" show Math;
|
||||||
|
import "package:angular2/angular2.dart" show Component, Directive, View;
|
||||||
|
import "common.dart"
|
||||||
|
show
|
||||||
|
Offering,
|
||||||
|
ITEMS,
|
||||||
|
ITEM_HEIGHT,
|
||||||
|
VISIBLE_ITEMS,
|
||||||
|
VIEW_PORT_HEIGHT,
|
||||||
|
ROW_WIDTH,
|
||||||
|
HEIGHT;
|
||||||
|
import "random_data.dart" show generateOfferings;
|
||||||
|
import "scroll_item.dart" show ScrollItemComponent;
|
||||||
|
import "package:angular2/directives.dart" show NgFor;
|
||||||
|
|
||||||
|
@Component(selector: "scroll-area", changeDetection: "ON_PUSH_OBSERVE")
|
||||||
|
@View(directives: const [ScrollItemComponent, NgFor], template: '''
|
||||||
|
<div>
|
||||||
|
<div id="scrollDiv"
|
||||||
|
[style.height.px]="viewPortHeight"
|
||||||
|
style="width: 1000px; border: 1px solid #000; overflow: scroll"
|
||||||
|
on-scroll="onScroll(\$event)">
|
||||||
|
<div id="padding"></div>
|
||||||
|
<div id="inner">
|
||||||
|
<scroll-item
|
||||||
|
template="ng-for #item of visibleItems"
|
||||||
|
[offering]="item">
|
||||||
|
</scroll-item>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>''')
|
||||||
|
class ScrollAreaComponent {
|
||||||
|
List<Offering> _fullList;
|
||||||
|
List<Offering> visibleItems;
|
||||||
|
num viewPortHeight;
|
||||||
|
var paddingDiv;
|
||||||
|
var innerDiv;
|
||||||
|
ScrollAreaComponent() {
|
||||||
|
this._fullList = generateOfferings(ITEMS);
|
||||||
|
this.visibleItems = [];
|
||||||
|
this.viewPortHeight = VIEW_PORT_HEIGHT;
|
||||||
|
this.onScroll(null);
|
||||||
|
}
|
||||||
|
onScroll(evt) {
|
||||||
|
var scrollTop = 0;
|
||||||
|
if (evt != null) {
|
||||||
|
var scrollDiv = evt.target;
|
||||||
|
if (this.paddingDiv == null) {
|
||||||
|
this.paddingDiv = scrollDiv.querySelector("#padding");
|
||||||
|
}
|
||||||
|
if (this.innerDiv == null) {
|
||||||
|
this.innerDiv = scrollDiv.querySelector("#inner");
|
||||||
|
this.innerDiv.style.setProperty("width", '''${ ROW_WIDTH}px''');
|
||||||
|
}
|
||||||
|
scrollTop = scrollDiv.scrollTop;
|
||||||
|
}
|
||||||
|
var iStart = Math.floor(scrollTop / ITEM_HEIGHT);
|
||||||
|
var iEnd = Math.min(iStart + VISIBLE_ITEMS + 1, this._fullList.length);
|
||||||
|
var padding = iStart * ITEM_HEIGHT;
|
||||||
|
if (this.innerDiv != null) {
|
||||||
|
this.innerDiv.style.setProperty("height", '''${ HEIGHT - padding}px''');
|
||||||
|
}
|
||||||
|
if (this.paddingDiv != null) {
|
||||||
|
this.paddingDiv.style.setProperty("height", '''${ padding}px''');
|
||||||
|
}
|
||||||
|
this.visibleItems = ListWrapper.slice(this._fullList, iStart, iEnd);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
library benchmarks.src.naive_infinite_scroll.scroll_item;
|
||||||
|
|
||||||
|
import "cells.dart"
|
||||||
|
show
|
||||||
|
CompanyNameComponent,
|
||||||
|
OpportunityNameComponent,
|
||||||
|
OfferingNameComponent,
|
||||||
|
StageButtonsComponent,
|
||||||
|
AccountCellComponent,
|
||||||
|
FormattedCellComponent;
|
||||||
|
import "package:angular2/angular2.dart" show Component, Directive, View;
|
||||||
|
import "common.dart"
|
||||||
|
show
|
||||||
|
Offering,
|
||||||
|
ITEM_HEIGHT,
|
||||||
|
COMPANY_NAME_WIDTH,
|
||||||
|
OPPORTUNITY_NAME_WIDTH,
|
||||||
|
OFFERING_NAME_WIDTH,
|
||||||
|
ACCOUNT_CELL_WIDTH,
|
||||||
|
BASE_POINTS_WIDTH,
|
||||||
|
KICKER_POINTS_WIDTH,
|
||||||
|
STAGE_BUTTONS_WIDTH,
|
||||||
|
BUNDLES_WIDTH,
|
||||||
|
DUE_DATE_WIDTH,
|
||||||
|
END_DATE_WIDTH,
|
||||||
|
AAT_STATUS_WIDTH;
|
||||||
|
|
||||||
|
@Component(selector: "scroll-item", properties: const ["offering"], changeDetection: "ON_PUSH_OBSERVE")
|
||||||
|
@View(
|
||||||
|
directives: const [
|
||||||
|
CompanyNameComponent,
|
||||||
|
OpportunityNameComponent,
|
||||||
|
OfferingNameComponent,
|
||||||
|
StageButtonsComponent,
|
||||||
|
AccountCellComponent,
|
||||||
|
FormattedCellComponent
|
||||||
|
],
|
||||||
|
template: '''
|
||||||
|
<div class="row"
|
||||||
|
[style.height.px]="itemHeight"
|
||||||
|
[style.line-height.px]="itemHeight"
|
||||||
|
style="font-size: 18px; display: flex; justify-content: space-between;">
|
||||||
|
<company-name [company]="offering.company"
|
||||||
|
[cell-width]="companyNameWidth">
|
||||||
|
</company-name>
|
||||||
|
<opportunity-name [opportunity]="offering.opportunity"
|
||||||
|
[cell-width]="opportunityNameWidth">
|
||||||
|
</opportunity-name>
|
||||||
|
<offering-name [offering]="offering"
|
||||||
|
[cell-width]="offeringNameWidth">
|
||||||
|
</offering-name>
|
||||||
|
<account-cell [account]="offering.account"
|
||||||
|
[cell-width]="accountCellWidth">
|
||||||
|
</account-cell>
|
||||||
|
<formatted-cell [value]="offering.basePoints"
|
||||||
|
[cell-width]="basePointsWidth">
|
||||||
|
</formatted-cell>
|
||||||
|
<formatted-cell [value]="offering.kickerPoints"
|
||||||
|
[cell-width]="kickerPointsWidth">
|
||||||
|
</formatted-cell>
|
||||||
|
<stage-buttons [offering]="offering"
|
||||||
|
[cell-width]="stageButtonsWidth">
|
||||||
|
</stage-buttons>
|
||||||
|
<formatted-cell [value]="offering.bundles"
|
||||||
|
[cell-width]="bundlesWidth">
|
||||||
|
</formatted-cell>
|
||||||
|
<formatted-cell [value]="offering.dueDate"
|
||||||
|
[cell-width]="dueDateWidth">
|
||||||
|
</formatted-cell>
|
||||||
|
<formatted-cell [value]="offering.endDate"
|
||||||
|
[cell-width]="endDateWidth">
|
||||||
|
</formatted-cell>
|
||||||
|
<formatted-cell [value]="offering.aatStatus"
|
||||||
|
[cell-width]="aatStatusWidth">
|
||||||
|
</formatted-cell>
|
||||||
|
</div>''')
|
||||||
|
class ScrollItemComponent {
|
||||||
|
Offering offering;
|
||||||
|
num itemHeight;
|
||||||
|
ScrollItemComponent() {
|
||||||
|
this.itemHeight = ITEM_HEIGHT;
|
||||||
|
}
|
||||||
|
get companyNameWidth {
|
||||||
|
return COMPANY_NAME_WIDTH;
|
||||||
|
}
|
||||||
|
get opportunityNameWidth {
|
||||||
|
return OPPORTUNITY_NAME_WIDTH;
|
||||||
|
}
|
||||||
|
get offeringNameWidth {
|
||||||
|
return OFFERING_NAME_WIDTH;
|
||||||
|
}
|
||||||
|
get accountCellWidth {
|
||||||
|
return ACCOUNT_CELL_WIDTH;
|
||||||
|
}
|
||||||
|
get basePointsWidth {
|
||||||
|
return BASE_POINTS_WIDTH;
|
||||||
|
}
|
||||||
|
get kickerPointsWidth {
|
||||||
|
return KICKER_POINTS_WIDTH;
|
||||||
|
}
|
||||||
|
get stageButtonsWidth {
|
||||||
|
return STAGE_BUTTONS_WIDTH;
|
||||||
|
}
|
||||||
|
get bundlesWidth {
|
||||||
|
return BUNDLES_WIDTH;
|
||||||
|
}
|
||||||
|
get dueDateWidth {
|
||||||
|
return DUE_DATE_WIDTH;
|
||||||
|
}
|
||||||
|
get endDateWidth {
|
||||||
|
return END_DATE_WIDTH;
|
||||||
|
}
|
||||||
|
get aatStatusWidth {
|
||||||
|
return AAT_STATUS_WIDTH;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
// helper script that will read out the url parameters
|
||||||
|
// and store them in appropriate form fields on the page
|
||||||
|
(function() {
|
||||||
|
var regex = /(\w+)=(\w+)/g;
|
||||||
|
var search = decodeURIComponent(location.search);
|
||||||
|
while (match = regex.exec(search)) {
|
||||||
|
var name = match[1];
|
||||||
|
var value = match[2];
|
||||||
|
var els = document.querySelectorAll('input[name="'+name+'"]');
|
||||||
|
var el;
|
||||||
|
for (var i=0; i<els.length; i++) {
|
||||||
|
el = els[i];
|
||||||
|
if (el.type === 'radio' || el.type === 'checkbox') {
|
||||||
|
el.checked = el.value === value;
|
||||||
|
} else {
|
||||||
|
el.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
Loading…
Reference in New Issue