TouchDevelop/lib/Link.ts

214 строки
8.1 KiB
TypeScript

///<reference path='refs.ts'/>
module TDev.RT {
export enum LinkKind
{
unknown,
media,
image,
email,
phoneNumber,
hyperlink,
radio,
address
}
//? A link to a video, image, email, phone number
//@ ctx(general,gckey,walltap,cloudfield,json) serializable
export class Link
extends RTValue
{
private _title : string = undefined;
private _description : string = undefined;
private _kind: LinkKind = undefined;
private _address: string = undefined;
private _location : Location_ = undefined;
constructor() {
super()
}
//public reuseKey() { return "" + this._title + this._description + this._address + this._kind + this._location; }
// ctx is ignored
public exportJson(ctx: JsonExportCtx): any {
return {
title: this._title,
description: this._description,
kind: this._kind && this._kind,
address: this._address,
location: this._location && this._location.exportJson(ctx)
}
}
public importJson(ctx: JsonImportCtx, json: any): RT.RTValue {
if (typeof json != "object") json = undefined;
this._title = ctx.importString(json, "title");
this._description = ctx.importString(json, "description");
this._kind = ctx.importNumber(json, "kind");
this._address = ctx.importString(json, "address");
this._location = ctx.importLocation(json, "location");
return this;
}
static mk(address : string, kind : LinkKind) : Link
{
var lnk = new Link();
lnk._address = address;
lnk._kind = kind;
return lnk;
}
public toString(): string {
var s = this.name();
return s;
}
//? Gets the name if any
//@ readsMutable
public name() : string {
if (this._description)
return this._title + " : " + this._description;
else
return this._title;
}
//? Sets the name
//@ writesMutable
public set_name(name : string ) : void {
this._description = "";
this._title = name;
}
public set_title(t : string) : void
{
this._title = t;
}
public set_description(d : string) : void
{
this._description = d;
}
//? Gets the location if any
//@ readsMutable
public location() : Location_ { return this._location; }
//? Sets the location
//@ writesMutable
public set_location(location:Location_) : void { this._location = location; }
//? Gets the url
//@ readsMutable
public address(): string { return this._address; }
//? Gets a picture pointing to this address. Only applies to `image` link kinds.
//@ readsMutable
public to_picture(): Picture {
if (this._kind != LinkKind.image) return undefined;
return Picture.fromUrlSync(this._address, true);
}
//? Gets the kind of asset - media, image, email, phone number, hyperlink, deep zoom link, radio
public kind(): string { return (enumToString(LinkKind, this._kind)).toLowerCase(); }
private slowlyloadingelement: HTMLElement;
private previouslyloaded = false;
public getViewCore(s: IStackFrame, b: BoxBase = null): HTMLElement
{
switch (this._kind)
{
case LinkKind.image:
var img = <HTMLImageElement>createElement("img");
img.setAttribute('class', 'wall-picture');
img.src = this.address();
img.alt = this.name();
this.slowlyloadingelement = img;
b.delayedlayout = true;
return img;
case LinkKind.media:
try {
if (/\.(mp3|wav|m4a)$/i.test(this.address())) {
var audio = <HTMLAudioElement>createElement("audio", "wall-media", this.name());
audio.src = this.address();
audio.controls = true;
audio.autobuffer = true;
(<any>audio).crossorigin = "anonymous";
audio.load();
this.slowlyloadingelement = audio;
return audio;
} else {
var video = <HTMLVideoElement>createElement("video", "wall-media", this.name());
video.src = this.address();
video.controls = true;
video.autobuffer = true;
(<any>video).crossorigin = "anonymous";
video.load();
this.slowlyloadingelement = video;
b.delayedlayout = true;
return video;
}
} catch(e) {
return div("item", div("wall-dialog-header", lf("invalid media")), div("wall-dialog-body", this.address()));
}
default:
var url = this.address();
var text = "go";
switch (this._kind)
{
case LinkKind.phoneNumber:
if (!/^tel:/i.test(url))
url = 'tel:' + url;
text = "call";
break;
case LinkKind.email:
if (!/^mailto:/i.test(url))
url = 'mailto:' + encodeURIComponent(url);
text = "send";
break;
}
var elt = div("item link-item",
[div("wall-dialog-header", this._title || this.address() || url),
this._description ? div("wall-dialog-body", this._description) : null])
elt.withClick(() => Web.browseAsync(url).done());
return elt;
}
}
public updateViewCore(s: IStackFrame, b: BoxBase) {
if (LayoutMgr.RenderExecutionMode() && this.slowlyloadingelement)
{
if (this.slowlyloadingelement.tagName == "IMG") {
this.slowlyloadingelement.onload = () => {
//Util.log("onload h=" + (<HTMLImageElement> this.slowlyloadingelement).height + " w=" + (<HTMLImageElement> this.slowlyloadingelement).width );
b.delayedlayout = false;
b.RefreshOnScreen();
}
this.slowlyloadingelement.onerror = () => {
// Util.log("onerror")
b.SwapImageContent(Picture.errorPic());
}
} else {
this.slowlyloadingelement.onloadedmetadata = () => {
//Util.log("onloadedmetadata h=" + (<HTMLImageElement> this.slowlyloadingelement).height + " w=" + (<HTMLImageElement> this.slowlyloadingelement).width );
b.delayedlayout = false;
b.RefreshOnScreen();
}
}
}
}
//? Shares the link (email, sms, facebook, social or '' to pick from a list)
//@ flow(SinkSharing) readsMutable uiAsync
//@ [network].defl("social")
public share(network: string, r : ResumeCtx): void
{
HTML.showProgressNotification(lf("sharing link..."));
ShareManager.shareLinkAsync(this, network).done(() => r.resume());
}
//? Displays the link on the wall
//@ flow(SinkWeb)
//@ readsMutable
public post_to_wall(s: IStackFrame): void { super.post_to_wall(s) }
}
}