mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
chore: format
This commit is contained in:
@@ -1,5 +1,16 @@
|
||||
import { ListView as ListViewDefinition, ItemsSource, ItemEventData, TemplatedItemsView } from ".";
|
||||
import { View, ContainerView, Template, KeyedTemplate, CSSType } from "../core/view";
|
||||
import {
|
||||
ListView as ListViewDefinition,
|
||||
ItemsSource,
|
||||
ItemEventData,
|
||||
TemplatedItemsView,
|
||||
} from ".";
|
||||
import {
|
||||
View,
|
||||
ContainerView,
|
||||
Template,
|
||||
KeyedTemplate,
|
||||
CSSType,
|
||||
} from "../core/view";
|
||||
import { Property, CoercibleProperty, CssProperty } from "../core/properties";
|
||||
import { Length } from "../styling/style-properties";
|
||||
import { Style } from "../styling/style";
|
||||
@@ -8,205 +19,269 @@ import { Builder } from "../builder";
|
||||
import { Label } from "../label";
|
||||
import { Observable, EventData } from "../../data/observable";
|
||||
import { ObservableArray, ChangedData } from "../../data/observable-array";
|
||||
import { addWeakEventListener, removeWeakEventListener } from "../core/weak-event-listener";
|
||||
import {
|
||||
addWeakEventListener,
|
||||
removeWeakEventListener,
|
||||
} from "../core/weak-event-listener";
|
||||
|
||||
// TODO: Think of a way to register these instead of relying on hardcoded values.
|
||||
export module knownTemplates {
|
||||
export const itemTemplate = "itemTemplate";
|
||||
export const itemTemplate = "itemTemplate";
|
||||
}
|
||||
|
||||
export module knownMultiTemplates {
|
||||
export const itemTemplates = "itemTemplates";
|
||||
export const itemTemplates = "itemTemplates";
|
||||
}
|
||||
|
||||
const autoEffectiveRowHeight = -1;
|
||||
|
||||
@CSSType("ListView")
|
||||
export abstract class ListViewBase extends ContainerView implements ListViewDefinition, TemplatedItemsView {
|
||||
public static itemLoadingEvent = "itemLoading";
|
||||
public static itemTapEvent = "itemTap";
|
||||
public static loadMoreItemsEvent = "loadMoreItems";
|
||||
// TODO: get rid of such hacks.
|
||||
public static knownFunctions = ["itemTemplateSelector", "itemIdGenerator"]; //See component-builder.ts isKnownFunction
|
||||
export abstract class ListViewBase extends ContainerView
|
||||
implements ListViewDefinition, TemplatedItemsView {
|
||||
public static itemLoadingEvent = "itemLoading";
|
||||
public static itemTapEvent = "itemTap";
|
||||
public static loadMoreItemsEvent = "loadMoreItems";
|
||||
// TODO: get rid of such hacks.
|
||||
public static knownFunctions = ["itemTemplateSelector", "itemIdGenerator"]; //See component-builder.ts isKnownFunction
|
||||
|
||||
private _itemIdGenerator: (item: any, index: number, items: any) => number = (_item: any, index: number) => index;
|
||||
private _itemTemplateSelector: (item: any, index: number, items: any) => string;
|
||||
private _itemTemplateSelectorBindable = new Label();
|
||||
public _defaultTemplate: KeyedTemplate = {
|
||||
key: "default",
|
||||
createView: () => {
|
||||
if (this.itemTemplate) {
|
||||
return Builder.parse(this.itemTemplate, this);
|
||||
}
|
||||
private _itemIdGenerator: (
|
||||
item: any,
|
||||
index: number,
|
||||
items: any
|
||||
) => number = (_item: any, index: number) => index;
|
||||
private _itemTemplateSelector: (
|
||||
item: any,
|
||||
index: number,
|
||||
items: any
|
||||
) => string;
|
||||
private _itemTemplateSelectorBindable = new Label();
|
||||
public _defaultTemplate: KeyedTemplate = {
|
||||
key: "default",
|
||||
createView: () => {
|
||||
if (this.itemTemplate) {
|
||||
return Builder.parse(this.itemTemplate, this);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
return undefined;
|
||||
},
|
||||
};
|
||||
|
||||
public _itemTemplatesInternal = new Array<KeyedTemplate>(this._defaultTemplate);
|
||||
public _effectiveRowHeight: number = autoEffectiveRowHeight;
|
||||
public rowHeight: Length;
|
||||
public iosEstimatedRowHeight: Length;
|
||||
public items: any[] | ItemsSource;
|
||||
public itemTemplate: string | Template;
|
||||
public itemTemplates: string | Array<KeyedTemplate>;
|
||||
public _itemTemplatesInternal = new Array<KeyedTemplate>(
|
||||
this._defaultTemplate
|
||||
);
|
||||
public _effectiveRowHeight: number = autoEffectiveRowHeight;
|
||||
public rowHeight: Length;
|
||||
public iosEstimatedRowHeight: Length;
|
||||
public items: any[] | ItemsSource;
|
||||
public itemTemplate: string | Template;
|
||||
public itemTemplates: string | Array<KeyedTemplate>;
|
||||
|
||||
get separatorColor(): Color {
|
||||
return this.style.separatorColor;
|
||||
}
|
||||
set separatorColor(value: Color) {
|
||||
this.style.separatorColor = value;
|
||||
}
|
||||
get separatorColor(): Color {
|
||||
return this.style.separatorColor;
|
||||
}
|
||||
set separatorColor(value: Color) {
|
||||
this.style.separatorColor = value;
|
||||
}
|
||||
|
||||
get itemTemplateSelector(): string | ((item: any, index: number, items: any) => string) {
|
||||
return this._itemTemplateSelector;
|
||||
}
|
||||
set itemTemplateSelector(value: string | ((item: any, index: number, items: any) => string)) {
|
||||
if (typeof value === "string") {
|
||||
this._itemTemplateSelectorBindable.bind({
|
||||
sourceProperty: null,
|
||||
targetProperty: "templateKey",
|
||||
expression: value
|
||||
});
|
||||
this._itemTemplateSelector = (item: any, index: number, items: any) => {
|
||||
item["$index"] = index;
|
||||
get itemTemplateSelector():
|
||||
| string
|
||||
| ((item: any, index: number, items: any) => string) {
|
||||
return this._itemTemplateSelector;
|
||||
}
|
||||
set itemTemplateSelector(
|
||||
value: string | ((item: any, index: number, items: any) => string)
|
||||
) {
|
||||
if (typeof value === "string") {
|
||||
this._itemTemplateSelectorBindable.bind({
|
||||
sourceProperty: null,
|
||||
targetProperty: "templateKey",
|
||||
expression: value,
|
||||
});
|
||||
this._itemTemplateSelector = (
|
||||
item: any,
|
||||
index: number,
|
||||
items: any
|
||||
) => {
|
||||
item["$index"] = index;
|
||||
|
||||
if (this._itemTemplateSelectorBindable.bindingContext === item) {
|
||||
this._itemTemplateSelectorBindable.bindingContext = null;
|
||||
}
|
||||
if (
|
||||
this._itemTemplateSelectorBindable.bindingContext === item
|
||||
) {
|
||||
this._itemTemplateSelectorBindable.bindingContext = null;
|
||||
}
|
||||
|
||||
this._itemTemplateSelectorBindable.bindingContext = item;
|
||||
this._itemTemplateSelectorBindable.bindingContext = item;
|
||||
|
||||
return this._itemTemplateSelectorBindable.get("templateKey");
|
||||
};
|
||||
}
|
||||
else if (typeof value === "function") {
|
||||
this._itemTemplateSelector = value;
|
||||
}
|
||||
}
|
||||
return this._itemTemplateSelectorBindable.get("templateKey");
|
||||
};
|
||||
} else if (typeof value === "function") {
|
||||
this._itemTemplateSelector = value;
|
||||
}
|
||||
}
|
||||
|
||||
get itemIdGenerator(): (item: any, index: number, items: any) => number {
|
||||
return this._itemIdGenerator;
|
||||
}
|
||||
set itemIdGenerator(generatorFn: (item: any, index: number, items: any) => number) {
|
||||
this._itemIdGenerator = generatorFn;
|
||||
}
|
||||
get itemIdGenerator(): (item: any, index: number, items: any) => number {
|
||||
return this._itemIdGenerator;
|
||||
}
|
||||
set itemIdGenerator(
|
||||
generatorFn: (item: any, index: number, items: any) => number
|
||||
) {
|
||||
this._itemIdGenerator = generatorFn;
|
||||
}
|
||||
|
||||
public refresh() {
|
||||
//
|
||||
}
|
||||
public refresh() {
|
||||
//
|
||||
}
|
||||
|
||||
public scrollToIndex(index: number) {
|
||||
//
|
||||
}
|
||||
public scrollToIndex(index: number) {
|
||||
//
|
||||
}
|
||||
|
||||
public scrollToIndexAnimated(index: number) {
|
||||
//
|
||||
}
|
||||
public scrollToIndexAnimated(index: number) {
|
||||
//
|
||||
}
|
||||
|
||||
public _getItemTemplate(index: number): KeyedTemplate {
|
||||
let templateKey = "default";
|
||||
if (this.itemTemplateSelector) {
|
||||
let dataItem = this._getDataItem(index);
|
||||
templateKey = this._itemTemplateSelector(dataItem, index, this.items);
|
||||
}
|
||||
public _getItemTemplate(index: number): KeyedTemplate {
|
||||
let templateKey = "default";
|
||||
if (this.itemTemplateSelector) {
|
||||
let dataItem = this._getDataItem(index);
|
||||
templateKey = this._itemTemplateSelector(
|
||||
dataItem,
|
||||
index,
|
||||
this.items
|
||||
);
|
||||
}
|
||||
|
||||
for (let i = 0, length = this._itemTemplatesInternal.length; i < length; i++) {
|
||||
if (this._itemTemplatesInternal[i].key === templateKey) {
|
||||
return this._itemTemplatesInternal[i];
|
||||
}
|
||||
}
|
||||
for (
|
||||
let i = 0, length = this._itemTemplatesInternal.length;
|
||||
i < length;
|
||||
i++
|
||||
) {
|
||||
if (this._itemTemplatesInternal[i].key === templateKey) {
|
||||
return this._itemTemplatesInternal[i];
|
||||
}
|
||||
}
|
||||
|
||||
// This is the default template
|
||||
return this._itemTemplatesInternal[0];
|
||||
}
|
||||
// This is the default template
|
||||
return this._itemTemplatesInternal[0];
|
||||
}
|
||||
|
||||
public _prepareItem(item: View, index: number) {
|
||||
if (item) {
|
||||
item.bindingContext = this._getDataItem(index);
|
||||
}
|
||||
}
|
||||
public _prepareItem(item: View, index: number) {
|
||||
if (item) {
|
||||
item.bindingContext = this._getDataItem(index);
|
||||
}
|
||||
}
|
||||
|
||||
private _getDataItem(index: number): any {
|
||||
let thisItems = <ItemsSource>this.items;
|
||||
private _getDataItem(index: number): any {
|
||||
let thisItems = <ItemsSource>this.items;
|
||||
|
||||
return thisItems.getItem ? thisItems.getItem(index) : thisItems[index];
|
||||
}
|
||||
return thisItems.getItem ? thisItems.getItem(index) : thisItems[index];
|
||||
}
|
||||
|
||||
public _getDefaultItemContent(index: number): View {
|
||||
let lbl = new Label();
|
||||
lbl.bind({
|
||||
targetProperty: "text",
|
||||
sourceProperty: "$value"
|
||||
});
|
||||
public _getDefaultItemContent(index: number): View {
|
||||
let lbl = new Label();
|
||||
lbl.bind({
|
||||
targetProperty: "text",
|
||||
sourceProperty: "$value",
|
||||
});
|
||||
|
||||
return lbl;
|
||||
}
|
||||
return lbl;
|
||||
}
|
||||
|
||||
public _onItemsChanged(args: ChangedData<any>) {
|
||||
this.refresh();
|
||||
}
|
||||
public _onItemsChanged(args: ChangedData<any>) {
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
public _onRowHeightPropertyChanged(oldValue: Length, newValue: Length) {
|
||||
this.refresh();
|
||||
}
|
||||
public _onRowHeightPropertyChanged(oldValue: Length, newValue: Length) {
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
public isItemAtIndexVisible(index: number) {
|
||||
return false;
|
||||
}
|
||||
public isItemAtIndexVisible(index: number) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected updateEffectiveRowHeight(): void {
|
||||
rowHeightProperty.coerce(this);
|
||||
}
|
||||
protected updateEffectiveRowHeight(): void {
|
||||
rowHeightProperty.coerce(this);
|
||||
}
|
||||
}
|
||||
ListViewBase.prototype.recycleNativeView = "auto";
|
||||
|
||||
export interface ListViewBase {
|
||||
on(eventNames: string, callback: (data: EventData) => void, thisArg?: any);
|
||||
on(event: "itemLoading", callback: (args: ItemEventData) => void, thisArg?: any);
|
||||
on(event: "itemTap", callback: (args: ItemEventData) => void, thisArg?: any);
|
||||
on(event: "loadMoreItems", callback: (args: EventData) => void, thisArg?: any);
|
||||
on(eventNames: string, callback: (data: EventData) => void, thisArg?: any);
|
||||
on(
|
||||
event: "itemLoading",
|
||||
callback: (args: ItemEventData) => void,
|
||||
thisArg?: any
|
||||
);
|
||||
on(
|
||||
event: "itemTap",
|
||||
callback: (args: ItemEventData) => void,
|
||||
thisArg?: any
|
||||
);
|
||||
on(
|
||||
event: "loadMoreItems",
|
||||
callback: (args: EventData) => void,
|
||||
thisArg?: any
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the property backing the items property of each ListView instance.
|
||||
*/
|
||||
export const itemsProperty = new Property<ListViewBase, any[] | ItemsSource>({
|
||||
name: "items", valueChanged: (target, oldValue, newValue) => {
|
||||
if (oldValue instanceof Observable) {
|
||||
removeWeakEventListener(oldValue, ObservableArray.changeEvent, target._onItemsChanged, target);
|
||||
}
|
||||
name: "items",
|
||||
valueChanged: (target, oldValue, newValue) => {
|
||||
if (oldValue instanceof Observable) {
|
||||
removeWeakEventListener(
|
||||
oldValue,
|
||||
ObservableArray.changeEvent,
|
||||
target._onItemsChanged,
|
||||
target
|
||||
);
|
||||
}
|
||||
|
||||
if (newValue instanceof Observable) {
|
||||
addWeakEventListener(newValue, ObservableArray.changeEvent, target._onItemsChanged, target);
|
||||
}
|
||||
if (newValue instanceof Observable) {
|
||||
addWeakEventListener(
|
||||
newValue,
|
||||
ObservableArray.changeEvent,
|
||||
target._onItemsChanged,
|
||||
target
|
||||
);
|
||||
}
|
||||
|
||||
target.refresh();
|
||||
}
|
||||
target.refresh();
|
||||
},
|
||||
});
|
||||
itemsProperty.register(ListViewBase);
|
||||
|
||||
/**
|
||||
* Represents the item template property of each ListView instance.
|
||||
*/
|
||||
export const itemTemplateProperty = new Property<ListViewBase, string | Template>({
|
||||
name: "itemTemplate", valueChanged: (target) => {
|
||||
target.refresh();
|
||||
}
|
||||
export const itemTemplateProperty = new Property<
|
||||
ListViewBase,
|
||||
string | Template
|
||||
>({
|
||||
name: "itemTemplate",
|
||||
valueChanged: (target) => {
|
||||
target.refresh();
|
||||
},
|
||||
});
|
||||
itemTemplateProperty.register(ListViewBase);
|
||||
|
||||
/**
|
||||
* Represents the items template property of each ListView instance.
|
||||
*/
|
||||
export const itemTemplatesProperty = new Property<ListViewBase, string | Array<KeyedTemplate>>({
|
||||
name: "itemTemplates", valueConverter: (value) => {
|
||||
if (typeof value === "string") {
|
||||
return Builder.parseMultipleTemplates(value, null);
|
||||
}
|
||||
export const itemTemplatesProperty = new Property<
|
||||
ListViewBase,
|
||||
string | Array<KeyedTemplate>
|
||||
>({
|
||||
name: "itemTemplates",
|
||||
valueConverter: (value) => {
|
||||
if (typeof value === "string") {
|
||||
return Builder.parseMultipleTemplates(value, null);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
return value;
|
||||
},
|
||||
});
|
||||
itemTemplatesProperty.register(ListViewBase);
|
||||
|
||||
@@ -215,22 +290,36 @@ const defaultRowHeight: Length = "auto";
|
||||
* Represents the observable property backing the rowHeight property of each ListView instance.
|
||||
*/
|
||||
export const rowHeightProperty = new CoercibleProperty<ListViewBase, Length>({
|
||||
name: "rowHeight", defaultValue: defaultRowHeight, equalityComparer: Length.equals,
|
||||
coerceValue: (target, value) => {
|
||||
// We coerce to default value if we don't have display density.
|
||||
return target.nativeViewProtected ? value : defaultRowHeight;
|
||||
},
|
||||
valueChanged: (target, oldValue, newValue) => {
|
||||
target._effectiveRowHeight = Length.toDevicePixels(newValue, autoEffectiveRowHeight);
|
||||
target._onRowHeightPropertyChanged(oldValue, newValue);
|
||||
}, valueConverter: Length.parse
|
||||
name: "rowHeight",
|
||||
defaultValue: defaultRowHeight,
|
||||
equalityComparer: Length.equals,
|
||||
coerceValue: (target, value) => {
|
||||
// We coerce to default value if we don't have display density.
|
||||
return target.nativeViewProtected ? value : defaultRowHeight;
|
||||
},
|
||||
valueChanged: (target, oldValue, newValue) => {
|
||||
target._effectiveRowHeight = Length.toDevicePixels(
|
||||
newValue,
|
||||
autoEffectiveRowHeight
|
||||
);
|
||||
target._onRowHeightPropertyChanged(oldValue, newValue);
|
||||
},
|
||||
valueConverter: Length.parse,
|
||||
});
|
||||
rowHeightProperty.register(ListViewBase);
|
||||
|
||||
export const iosEstimatedRowHeightProperty = new Property<ListViewBase, Length>({
|
||||
name: "iosEstimatedRowHeight", valueConverter: (v) => Length.parse(v)
|
||||
});
|
||||
export const iosEstimatedRowHeightProperty = new Property<ListViewBase, Length>(
|
||||
{
|
||||
name: "iosEstimatedRowHeight",
|
||||
valueConverter: (v) => Length.parse(v),
|
||||
}
|
||||
);
|
||||
iosEstimatedRowHeightProperty.register(ListViewBase);
|
||||
|
||||
export const separatorColorProperty = new CssProperty<Style, Color>({ name: "separatorColor", cssName: "separator-color", equalityComparer: Color.equals, valueConverter: (v) => new Color(v) });
|
||||
export const separatorColorProperty = new CssProperty<Style, Color>({
|
||||
name: "separatorColor",
|
||||
cssName: "separator-color",
|
||||
equalityComparer: Color.equals,
|
||||
valueConverter: (v) => new Color(v),
|
||||
});
|
||||
separatorColorProperty.register(Style);
|
||||
|
||||
Reference in New Issue
Block a user