Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
152 lines
4.9 KiB
JavaScript
Executable file
152 lines
4.9 KiB
JavaScript
Executable file
'use strict';
|
|
/* global
|
|
MediaUtils,
|
|
ThumbnailItem
|
|
*/
|
|
|
|
/**
|
|
* ThumbnailDateGroup is a grouping mechanism supported in gallery app. It
|
|
* groups file data by its year and month. The grouping
|
|
* identity is based on the groupID. Once the groupID is different, we view
|
|
* two groups as different groups. ThumbnailDateGroup also sorts the added file
|
|
* data descendant. We can just put a item into group and let it sort the list.
|
|
*
|
|
* CONSTRUCTOR:
|
|
* To create a group, we need to supply one argument:
|
|
* item: the first data object for this group. It will be used for
|
|
* rendering the information about this group.
|
|
*
|
|
* API:
|
|
* addItem(): add a new item to this group. ThumbnailDateGroup will create a
|
|
* ThumbnailItem for the supplied file data and insert it to UI.
|
|
* args:
|
|
* item: the file data object.
|
|
* return: ThumbnailItem object
|
|
* removeItem(): remove a ThumbnailItem from this group. It also removes the
|
|
* UI from this group.
|
|
* thumbnail: ThumbnailItem object to remove.
|
|
* getCount(): returns the total items in this group
|
|
*
|
|
* Properties:
|
|
* htmlNode: the HTML DOM node of this group.
|
|
* groupID: the ID of this group.
|
|
* thumbnails: all ThumbnailItem objects under this group.
|
|
*
|
|
* Static API:
|
|
* getGroupID: calculate the group id for file object.
|
|
* item: the file data object.
|
|
* return: an id string.
|
|
* compareGroupID: Compare group ids in format group_yyyy-mm.
|
|
* The format is chosen carefully so that string comparison
|
|
* returns the same result as numeric comparison
|
|
*
|
|
*/
|
|
function ThumbnailDateGroup(item) {
|
|
if (!item) {
|
|
throw new Error('item should not be null or undefined.');
|
|
}
|
|
|
|
this.thumbnails = [];
|
|
this.groupID = ThumbnailDateGroup.getGroupID(item);
|
|
this.date = item.date;
|
|
|
|
// Create the DOM elements for this thumbnail group
|
|
this.header = document.createElement('div');
|
|
this.header.className = 'thumbnail-group-header';
|
|
this.container = document.createElement('div');
|
|
this.container.className = 'thumbnail-group-container';
|
|
this.htmlNode = document.createElement('li');
|
|
this.htmlNode.appendChild(this.header);
|
|
this.htmlNode.appendChild(this.container);
|
|
|
|
this.localize();
|
|
}
|
|
|
|
ThumbnailDateGroup.getGroupID = function(item) {
|
|
// id is group_yyyy-mm. this id will be used as a key
|
|
var dateObj = new Date(item.date);
|
|
var month = dateObj.getMonth() + 1;
|
|
return 'group_' + dateObj.getFullYear() + '-' +
|
|
(month < 10 ? '0' + month : month);
|
|
};
|
|
|
|
ThumbnailDateGroup.compareGroupID = function(id1, id2) {
|
|
return id1 > id2 ? 1 : (id1 < id2 ? -1 : 0);
|
|
};
|
|
|
|
// Instance methods
|
|
ThumbnailDateGroup.prototype.addItem = function(item) {
|
|
if (!item) {
|
|
return;
|
|
}
|
|
|
|
var self = this;
|
|
|
|
function getInsertPosition(thumbnail) {
|
|
if (self.thumbnails.length === 0 ||
|
|
thumbnail.data.date > self.thumbnails[0].data.date) {
|
|
// This file is the first or is newer than the first one.
|
|
// This is the most common case for new files.
|
|
return 0;
|
|
}
|
|
else if (thumbnail.data.date <
|
|
self.thumbnails[self.thumbnails.length - 1].data.date) {
|
|
// This file is older than the last one.
|
|
// This is the most common case when we enumerate the database.
|
|
return self.thumbnails.length;
|
|
}
|
|
else {
|
|
// Otherwise we have to search for the right insertion spot
|
|
return MediaUtils.binarySearch(self.thumbnails,
|
|
thumbnail,
|
|
function(a, b) {
|
|
return b.data.date - a.data.date;
|
|
});
|
|
}
|
|
}
|
|
|
|
var thumbnail = new ThumbnailItem(item);
|
|
// calculate the position.
|
|
var insertPosition = getInsertPosition(thumbnail);
|
|
// put into DOM tree.
|
|
this.container.insertBefore(thumbnail.htmlNode,
|
|
this.container.children[insertPosition]);
|
|
// insert thumbnail view into array
|
|
this.thumbnails.splice(insertPosition, 0, thumbnail);
|
|
return thumbnail;
|
|
};
|
|
|
|
ThumbnailDateGroup.prototype.getCount = function() {
|
|
return this.thumbnails.length;
|
|
};
|
|
|
|
ThumbnailDateGroup.prototype.removeItem = function(thumbnail) {
|
|
var idx = this.thumbnails.indexOf(thumbnail);
|
|
if (idx < 0) {
|
|
return;
|
|
}
|
|
this.thumbnails.splice(idx, 1);
|
|
URL.revokeObjectURL(thumbnail.imgNode.src);
|
|
this.container.removeChild(thumbnail.htmlNode);
|
|
};
|
|
|
|
ThumbnailDateGroup.formatter = new Intl.DateTimeFormat(navigator.languages, {
|
|
month: 'long',
|
|
year: 'numeric',
|
|
});
|
|
|
|
ThumbnailDateGroup.resetFormatter = () => {
|
|
ThumbnailDateGroup.formatter = new Intl.DateTimeFormat(navigator.languages, {
|
|
month: 'long',
|
|
year: 'numeric',
|
|
});
|
|
};
|
|
|
|
ThumbnailDateGroup.prototype.localize = function() {
|
|
var date = new Date(this.date);
|
|
|
|
this.header.textContent = ThumbnailDateGroup.formatter.format(date);
|
|
|
|
// Localize each of the group's thumbnails.
|
|
this.thumbnails.forEach(function(thumbnail) { thumbnail.localize(); });
|
|
};
|