Skip to content

Commit

Permalink
Separate the concerns of the dismissal from the data and ScrollingEngine
Browse files Browse the repository at this point in the history
The app-dismissable-list now fires a 'dismiss-items' event, which is
hooked up to the data provider. When the data provider is changed it
sends out a custom event 'data-changed' which is ScrollingEngine
listens to.

For this to work a proper FakeDataProvider object has been created.
  • Loading branch information
kenchris committed Feb 19, 2014
1 parent 4e6004f commit c0e0be9
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 47 deletions.
31 changes: 7 additions & 24 deletions app-widgets.html
Original file line number Diff line number Diff line change
Expand Up @@ -138,23 +138,6 @@
onItemAnimate: function(item, position) {
item.style.WebkitTransform = 'translate3d(0,' + position + 'px,0)';
},
removeItemsFromBackend: function() {
var self = this;
this.itemsToRemove.forEach(function(item) {
fakeData.some(function(element, index) {
if (element.id == item.id) {
fakeData.splice(index, 1);
return true;
}
})

item.style.opacity = '';
});
this.itemsToRemove = [];

var item = this.children[0];
item.parentElement.parentElement.engine.refresh_(true);
},
removeItems: function() {
// To simplify the math in dismissItem, wait until all the dismiss animations are done before
// removing the dismissed items from the DOM.
Expand All @@ -164,13 +147,15 @@
return;
}

this.removeItemsFromBackend();
this.fire('dismiss-items', { items: this.itemsToRemove });
this.itemsToRemove = [];

for (var i = 1, len = this.children.length; i < len; ++i) {
var item = this.children[i];
if (item.animationController)
item.animationController.stopAnimation();
item.animationController = null;
item.style.opacity = '';
}
},
dismissItem: function(item) {
Expand Down Expand Up @@ -250,7 +235,8 @@
var currentY = getTransformValue(item);
item.style.WebkitTransform = 'translate3d(0,' + currentY + 'px,0)';

self.removeItemsFromBackend();
this.fire('dismiss-items', { items: this.itemsToRemove });
this.itemsToRemove = [];
}.bind(this);

item.addEventListener('webkitTransitionEnd', onTransitionEnd);
Expand Down Expand Up @@ -355,15 +341,12 @@
count: 500,
enteredView: function() {
this.$.runway.style.height = this.height * this.count + 'px';
this.data = new FakeDataProvider(this.count);
this.engine = new ScrollingEngine({
height: this.height,
count: this.count,
container: this,
template: this.querySelector('template'),
dataProvider: function(i) {
// TODO(abarth): We should get data from this.data rather than from the global fakeListData.
return fakeListData[i % fakeListData.length];
},
dataProvider: this.data,
});
},
});
Expand Down
77 changes: 58 additions & 19 deletions data.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
(function(exports) {
'use strict';

function repeat(s, n) {
return Array(n + 1).join(s);
}

function generateFakeDrawerData(numberOfItems) {
var data = [];
var i = 0;
while (i < numberOfItems) {
data[i] = {
icon: 'dialog',
label: repeat(String.fromCharCode(65 + i++), 5)
};
}
data[i] = {icon: 'search', label: 'Search'};
return data;
}

function getRandomItem(array) {
return array[Math.floor(Math.random() * array.length)];
}

function generateFakeListData() {
var kNumberOfItems = 500;
function generateFakeListData(numberOfItems) {
var possibleAvatarColors = [
'BurlyWood', 'green', 'orange', 'salmon', 'lightblue', 'BlueViolet', 'DarkSeaGreen',
];
Expand All @@ -27,8 +43,9 @@ function generateFakeListData() {
'When, in disgrace with fortune and men\'s eyes, I all alone beweep my outcast state,',
'We the People of the United States, in Order to form a more perfect Union, establish Justice, insure domestic Tranquility',
];

var data = [];
for (var i = 0; i < kNumberOfItems; ++i) {
for (var i = 0; i < numberOfItems; ++i) {
data[i] = {
id: i,
avatarColor: getRandomItem(possibleAvatarColors),
Expand All @@ -42,25 +59,47 @@ function generateFakeListData() {
return data;
}

function repeat(s, n) {
return Array(n + 1).join(s);
function FakeDataProvider(numberOfItems) {
// Create a HTMLUnknownElement and do not attach it to the DOM.
this.dispatcher_ = document.createElement('FakeDataProvider-EventDispatcher');
this.data_ = generateFakeListData(numberOfItems);
}

function generateFakeDrawerData() {
var kNumberOfItems = 26;
var data = [];
var i = 0;
while (i < kNumberOfItems) {
data[i] = {
icon: 'dialog',
label: repeat(String.fromCharCode(65 + i++), 5)
};
}
data[i] = {icon: 'search', label: 'Search'};
return data;
FakeDataProvider.prototype.addEventListener = function(type, callback, capture) {
this.dispatcher_.addEventListener(type, callback, capture);
}

FakeDataProvider.prototype.removeEventListener = function(type, callback, capture) {
this.dispatcher_.removeEventListener(type, callback, capture);
}

FakeDataProvider.prototype.dispatchEvent = function(e) {
this.dispatcher_.dispatchEvent(e);
}

FakeDataProvider.prototype.getItemCount = function() {
return this.data_.length;
}

FakeDataProvider.prototype.getItem = function(index) {
return this.data_[index % this.data_.length];
}

FakeDataProvider.prototype.deleteItemByIds = function(ids) {
self = this;
ids.forEach(function(id) {
self.data_.some(function(element, index) {
if (element.id == id) {
self.data_.splice(index, 1);
return true;
}
})
})
var event = new CustomEvent("data-changed", { items: ids });
this.dispatchEvent(event);
}

exports.fakeListData = generateFakeListData();
exports.fakeDrawerData = generateFakeDrawerData();
exports.FakeDataProvider = FakeDataProvider;
exports.fakeDrawerData = generateFakeDrawerData(26);

})(window);
4 changes: 4 additions & 0 deletions demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@
templateElement.model = fakeDrawerData;
navDrawer.toggle();
});
document.querySelector('app-dismissable-list').addEventListener('dismiss-items', function(e) {
var dataProvider = e.target.parentElement.data;
dataProvider.deleteItemByIds(e.detail.items.map(function(item) { return item.id; }));
});
});
</script>
</body>
Expand Down
10 changes: 6 additions & 4 deletions scrolling.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ var kPhysicalRunway = 10;

function ScrollingEngine(options) {
this.height_ = options.height;
this.count_ = options.count;

this.dataProvider_ = options.dataProvider;
this.template_ = options.template;
Expand All @@ -20,7 +19,7 @@ function ScrollingEngine(options) {
this.physicalData_ = new Array(this.physicalCount_);
for (var i = 0; i < this.physicalCount_; ++i)
this.physicalData_[i] = {};
var exampleDatum = this.dataProvider_(0);
var exampleDatum = this.dataProvider_.getItem(0);
this.propertyNames_ = Object.getOwnPropertyNames(exampleDatum);

this.template_.model = this.physicalData_;
Expand All @@ -42,10 +41,13 @@ function ScrollingEngine(options) {
this.container_.addEventListener('scroll', function(e) {
self.onScroll_(e);
});
this.dataProvider_.addEventListener('data-changed', function(e) {
self.refresh_(true);
});
}

ScrollingEngine.prototype.updateItem_ = function(virtualIndex, physicalIndex) {
var virtualDatum = this.dataProvider_(virtualIndex);
var virtualDatum = this.dataProvider_.getItem(virtualIndex);
var physicalDatum = this.physicalData_[physicalIndex];

for (var i = 0; i < this.propertyNames_.length; ++i) {
Expand All @@ -65,7 +67,7 @@ ScrollingEngine.prototype.refresh_ = function(force) {
var visibleMidpoint = firstVisibleIndex + this.visibleCount_ / 2;

var firstReifiedIndex = Math.max(0, Math.floor(visibleMidpoint - this.physicalCount_ / 2));
firstReifiedIndex = Math.min(firstReifiedIndex, this.count_ - this.physicalCount_);
firstReifiedIndex = Math.min(firstReifiedIndex, this.dataProvider_.getItemCount() - this.physicalCount_);

var firstPhysicalIndex = firstReifiedIndex % this.physicalCount_;
var baseVirtualIndex = firstReifiedIndex - firstPhysicalIndex;
Expand Down

0 comments on commit c0e0be9

Please sign in to comment.