Pull over Mix ink definition and storage

This commit is contained in:
Kurt Berglund 2017-01-30 19:20:13 -08:00
Родитель f240370aae
Коммит 49e4e64bea
29 изменённых файлов: 517 добавлений и 274 удалений

Просмотреть файл

22
Dockerfile Normal file
Просмотреть файл

@ -0,0 +1,22 @@
FROM node:6.9.4-alpine
# Install gulp for building services
RUN npm install -g gulp
# Copy over and build ot-ink
COPY ./ot-ink /usr/src/ot-ink
WORKDIR /usr/src/ot-ink
RUN npm install
RUN gulp
# Copy over and build the server
COPY ./server /usr/src/server
WORKDIR /usr/src/server
RUN npm install
RUN gulp
# Expose the port the app runs under
EXPOSE 3000
# And set the default command to start the server
CMD ["npm", "start"]

Просмотреть файл

@ -5,7 +5,7 @@ services:
ports:
- "3000:3000"
volumes:
- .:/usr/src/server
- .:/usr/src/
depends_on:
- mongodb
- redis

59
ot-ink/src/definitions.ts Normal file
Просмотреть файл

@ -0,0 +1,59 @@
/**
* Kind of MixInk action which is used to decide if current action is for draring, moving or clearing canvas
*/
export enum MixInkActionKind {
Move = 0,
Draw = 1,
Clear = 2,
}
/**
* The action which is used to draw strokes
*/
export interface IMixInkAction {
// Milliseconds since start of MixInking when this stroke should be drawn
time: number;
// Move or darw
kind: MixInkActionKind;
// x coordinate
x: number;
// y coordinate
y: number;
// Pen data if the pen has changed with this stroke
pen?: IPen;
};
/**
* Pen data for the current stroke
*/
export interface IPen {
// Color in web format #rrggbb
color: string;
// Thickness of pen in pixels
thickness: number;
// Width and height for highlighter brush type
width?: number;
height?: number;
// Brush type, by default b is 0
brush?: number;
}
export enum MixInkBlush {
Pen = 0,
Eraser = 1,
Highlighter = 2,
}
export enum SegmentCircleInclusive {
None,
Both,
Start,
End,
}

Просмотреть файл

@ -1,16 +0,0 @@
FROM node:6.9.4-alpine
# Copy over the app source
COPY . /usr/src/server
WORKDIR /usr/src/server
# Install packages and then install the app
RUN npm install -g gulp
RUN npm install
RUN gulp
# Expose the port the app runs under
EXPOSE 3000
# And set the default command to start the server
CMD ["npm", "start"]

Просмотреть файл

@ -52,7 +52,7 @@ let controllers = [
{ name: "api", src: "src/api/index.ts", outFile: "api.js", folder: "public/dist/api", standalone: "pronet" },
{ name: "calendar", src: "src/calendar/driver.ts", outFile: "driver.js", folder: "public/dist/views/calendar", standalone: "calendar" },
{ name: "collab", src: "src/collab/collab.ts", outFile: "collab.js", folder: "public/dist/collab", standalone: "collab" },
{ name: "canvas", src: "src/canvas/canvas.ts", outFile: "canvas.js", folder: "public/dist/canvas", standalone: "canvas" },
{ name: "canvas", src: "src/canvas/index.ts", outFile: "canvas.js", folder: "public/dist/canvas", standalone: "canvas" },
];
// Generate tasks for the browserified code

Просмотреть файл

@ -39,7 +39,7 @@ export function createOrGetUser(
details: IUserDetails): Promise<any> {
return accounts.getAccount(provider, providerId).then((account) => {
// Check to see if there is an account - if not we need to create a new user
// Check to see if there is an account - if not we need to create a new user
let userIdP;
if (account === null) {
// Create a user first and then link this account to it

Просмотреть файл

@ -30,7 +30,7 @@ export class PostMessageHost implements IHost {
public start() {
this.host = postMessageSockets.getOrCreateHost(this.window);
// TODO for security we may need to define a set of allowed hosts -
// TODO for security we may need to define a set of allowed hosts -
// especially if the iframe conveys secret information to the host
this.socketP = this.host.connect(window.parent, "*");

Просмотреть файл

@ -54,7 +54,7 @@ if (nconf.get("redis")) {
servername: nconf.get("redis:host"),
};
// Azure seems to lose our Redis client for SSL connections - we ping it to keep it alive.
// Azure seems to lose our Redis client for SSL connections - we ping it to keep it alive.
setInterval(() => {
redisClient.ping((error, result) => {
if (error) {
@ -301,7 +301,7 @@ app.use((request, response, next) => {
if (!request.session) {
return next(new Error("Session not available"));
} else {
next(); // otherwise continue
next(); // otherwise continue
}
});
app.use(passport.initialize());

Просмотреть файл

@ -15,8 +15,8 @@ import {
} from "../api/index";
import { ICalendar, ICalendarEvent } from "./interfaces";
// The TypeScript compiler will elide these two libraries since they aren"t directly accessed.
// They are jquery plugins and so internally attach themselves to the $ object. We do the import
// The TypeScript compiler will elide these two libraries since they aren"t directly accessed.
// They are jquery plugins and so internally attach themselves to the $ object. We do the import
// below to force their inclusion while also keeping the version above to get the typing information
import "fullcalendar";
import "qtip2";
@ -155,7 +155,7 @@ class CalendarViewModel {
}
this.tableP.then((table) => {
// Longer term we should standardize on some format here so there
// Longer term we should standardize on some format here so there
// isn't a disconnect between Office and moment
const columnTimeFormatString = "m/d/yy h:mm AM/PM";
let columns = [
@ -168,7 +168,7 @@ class CalendarViewModel {
{ name: "responseStatus", format: null },
];
// Get and store the rows we will bind to the pnhost table -
// Get and store the rows we will bind to the pnhost table -
// we convert times to a format easier to parse by hosts (i.e. Excel)
const formatString = "M/D/YY h:mm A";
this.tableBoundRows = [];
@ -190,7 +190,7 @@ class CalendarViewModel {
// Load the rows into the hosted table
table.loadData(columns, this.tableBoundRows);
// Setup a table listener if it doesn"t already exist
// Setup a table listener if it doesn"t already exist
if (!this.tableListener) {
this.tableListener = new TableListener(this);
table.addListener(this.tableListener);
@ -200,7 +200,7 @@ class CalendarViewModel {
private loadAndCacheCalendars(): Promise<ICalendar[]> {
return this.calendar.getCalendars().then((calendars) => {
// Clear any pending deletes - a reload resets any interactions
// Clear any pending deletes - a reload resets any interactions
this.pendingDeletes = [];
// Initialize the custom UI once we load the first batch of data

Просмотреть файл

@ -1,4 +1,4 @@
import { App } from "./canvas";
import Canvas from "./canvas";
import * as utils from "./utils";
export default class BackBoard {
@ -8,7 +8,7 @@ export default class BackBoard {
private div: HTMLElement;
private gesture: MSGesture;
constructor(private appObject: App, htmlId: string) {
constructor(private appObject: Canvas, htmlId: string) {
this.div = utils.id(htmlId);
// tslint:disable-next-line:no-string-literal
this.div["sysObject"] = this;

Просмотреть файл

@ -12,17 +12,18 @@ sharedb.types.register(otInk.type);
// tslint:disable:no-console
// App Class
export class App {
/**
* Canvas app
*/
export default class Canvas {
public ink: InkCanvas;
public handleKeys: boolean = true;
public stickyCount: number = 0;
constructor() {
// register all of the different handlers
let p: HTMLElement = utils.id("hitPlane");
let p = document.getElementById("hitPlane");
this.ink = new InkCanvas(p);
window.addEventListener("keydown", (evt) => this.keyPress(evt), false);
@ -93,7 +94,7 @@ export class App {
this.ink.clear();
let board = utils.id("content");
let stickies = document.querySelectorAll(".stickyNote");
// tslint:disable-next-line:prefer-for-of:stickies is NodeListOf not an array
// tslint:disable-next-line:prefer-for-of
for (let i = 0; i < stickies.length; i++) {
board.removeChild(stickies[i]);
}
@ -137,46 +138,3 @@ export class App {
}
}
}
export function initialize(id: string) {
// Open WebSocket connection to ShareDB server
let protocol = window.location.protocol.indexOf("https") !== -1 ? "wss" : "ws";
let socket = new WebSocket(`${protocol}://${window.location.host}`);
let connection = new sharedb.Connection(socket);
// create the new app
$("document").ready(() => {
let appObject = new App();
let sticky = new StickyNote(utils.id("content"));
let mainBoard = new BackBoard(appObject, "hitPlane");
// id("ToolBar").appendChild(new ToolBarButton("images/icons/pencil.svg").click(appObject.clear).elem());
let doc = connection.get("canvas", id);
doc.subscribe((err) => {
if (err) {
throw err;
}
// If there is no type we need to create the document
if (!doc.type) {
console.log("Creating new document");
doc.create("Hello", otInk.type.name);
}
console.log(doc.data);
// To write more data
doc.submitOp(
{ position: 3, text: "World, " },
{ source: appObject });
doc.on("op", (op, source) => {
if (source === appObject) {
return;
}
// Update the canvas
});
});
});
}

Просмотреть файл

@ -0,0 +1,63 @@
// The main app code
import * as $ from "jquery";
import * as otInk from "ot-ink";
import * as sharedb from "sharedb/lib/client";
import BackBoard from "./backBoard";
import Canvas from "./canvas";
import InkCanvas from "./inkCanvas";
import StickyNote from "./stickyNote";
import * as utils from "./utils";
// tslint:disable:no-console
// Register the use of the rich text OT format
sharedb.types.register(otInk.type);
// throttle resize events and replace with an optimized version
utils.throttle("resize", "throttled-resize");
// TODO export the ability to get events?
export function initialize(id: string) {
// Open WebSocket connection to ShareDB server
let protocol = window.location.protocol.indexOf("https") !== -1 ? "wss" : "ws";
let socket = new WebSocket(`${protocol}://${window.location.host}`);
let connection = new sharedb.Connection(socket);
let doc = connection.get("canvas", id);
// create the new app
$("document").ready(() => {
let canvas = new Canvas();
let sticky = new StickyNote(utils.id("content"));
let mainBoard = new BackBoard(canvas, "hitPlane");
// id("ToolBar").appendChild(new ToolBarButton("images/icons/pencil.svg").click(appObject.clear).elem());
doc.subscribe((err) => {
if (err) {
throw err;
}
// If there is no type we need to create the document
if (!doc.type) {
console.log("Creating new document");
doc.create("Hello", otInk.type.name);
}
console.log(doc.data);
// To write more data
doc.submitOp(
{ position: 3, text: "World, " },
{ source: canvas });
doc.on("op", (op, source) => {
if (source === canvas) {
return;
}
// Update the canvas
});
});
});
}

Просмотреть файл

@ -4,202 +4,224 @@ import * as utils from "./utils";
// tslint:disable:max-classes-per-file
interface IPtrEvtPoint {
x: number;
y: number;
x: number;
y: number;
}
interface IPointerPointProps {
isEraser: boolean;
isEraser: boolean;
}
class EventPoint {
public rawPosition: IPtrEvtPoint;
public properties: IPointerPointProps;
public rawPosition: IPtrEvtPoint;
public properties: IPointerPointProps;
constructor(evt: PointerEvent) {
this.rawPosition = { x: evt.x, y: evt.y };
this.properties = { isEraser: false };
}
constructor(evt: PointerEvent) {
this.rawPosition = { x: evt.x, y: evt.y };
this.properties = { isEraser: false };
}
}
export default class InkCanvas {
public canvas: HTMLCanvasElement;
public context: CanvasRenderingContext2D;
public penID: number = -1;
public gesture: MSGesture;
public canvas: HTMLCanvasElement;
public context: CanvasRenderingContext2D;
public penID: number = -1;
public gesture: MSGesture;
// constructor
constructor(parent: HTMLElement) {
// setup canvas
this.canvas = document.createElement("canvas");
this.canvas.classList.add("drawSurface");
parent.appendChild(this.canvas);
// constructor
constructor(parent: HTMLElement) {
// setup canvas
this.canvas = document.createElement("canvas");
this.canvas.classList.add("drawSurface");
parent.appendChild(this.canvas);
// get context
this.context = this.canvas.getContext("2d");
// get context
this.context = this.canvas.getContext("2d");
let w: number = this.canvas.offsetWidth;
let h: number = this.canvas.offsetHeight;
let bb = false;
this.canvas.addEventListener("pointerdown", (evt) => this.handlePointerDown(evt), bb);
this.canvas.addEventListener("pointermove", (evt) => this.handlePointerMove(evt), bb);
this.canvas.addEventListener("pointerup", (evt) => this.handlePointerUp(evt), bb);
// set the width and height specified through CSS
this.canvas.setAttribute("width", w.toString());
this.canvas.setAttribute("height", h.toString());
// Set the initial size of hte canvas and then register for resize events to be able to update it
this.resize(this.canvas.offsetWidth, this.canvas.offsetHeight);
window.addEventListener("throttled-resize", (event) => {
this.resize(this.canvas.offsetWidth, this.canvas.offsetHeight);
});
}
// tslint:disable:no-empty
// Stubs for bunch of functions that are being called in the code below
// this will make it easier to fill some code in later or just delete them
let bb = false;
this.canvas.addEventListener("pointerdown", (evt) => this.handlePointerDown(evt), bb);
this.canvas.addEventListener("pointermove", (evt) => this.handlePointerMove(evt), bb);
this.canvas.addEventListener("pointerup", (evt) => this.handlePointerUp(evt), bb);
}
// tslint:disable:no-empty
// Stubs for bunch of functions that are being called in the code below
// this will make it easier to fill some code in later or just delete them
public tempEraseMode() {
}
public restoreMode() {
}
public renderAllStrokes() {
}
public anchorSelection() {
}
public selectAll() {
}
public inkMode() {
}
public inkColor() {
}
public undo() {
}
public redo() {
}
// tslint:enable:no-empty
public anySelected(): boolean {
return false;
}
// We will accept pen down or mouse left down as the start of a stroke.
// We will accept touch down or mouse right down as the start of a touch.
public handlePointerDown(evt) {
this.penID = evt.pointerId;
if (evt.pointerType === "touch") {
// ic.gesture.addPointer(evt.pointerId);
public tempEraseMode() {
}
if ((evt.pointerType === "pen") || ((evt.pointerType === "mouse") && (evt.button === 0))) {
// Anchor and clear any current selection.
this.anchorSelection();
let pt = new EventPoint(evt);
if (pt.properties.isEraser) { // The back side of a pen, which we treat as an eraser
this.tempEraseMode();
} else {
this.restoreMode();
}
this.context.beginPath();
this.context.moveTo(pt.rawPosition.x, pt.rawPosition.y);
let pressureWidth = evt.pressure * 15;
this.context.lineWidth = pressureWidth;
evt.returnValue = false;
}
}
public handlePointerMove(evt) {
if (evt.pointerId === this.penID) {
let pt = new EventPoint(evt);
let w = 8;
let h = 8;
if (evt.pointerType === "touch") {
this.context.strokeStyle = "gray";
w = evt.width;
h = evt.height;
// context.strokeRect(evt.x - w/2 - 1, evt.y - h/2 -1 , w+1, h+1);
this.context.clearRect(evt.x - w / 4, evt.y - h / 4, w / 2, h / 2);
evt.returnValue = false;
return false; // we"re going to clearRect instead
}
if (evt.pointerType === "pen") {
this.context.strokeStyle = "rgba(0, 50, 0, 1)";
w = w * (0.1 + evt.pressure);
h = h * (0.1 + evt.pressure);
} else { // just mouse
this.context.strokeStyle = "rgba(250, 0, 0, 0.5)";
}
this.context.lineWidth = w;
this.context.lineTo(evt.clientX, evt.clientY);
this.context.stroke();
evt.returnValue = false;
// let pts = evt.intermediatePoints;
// for (let i = pts.length - 1; i >= 0 ; i--) {
// }
}
return false;
}
public handlePointerUp(evt) {
if (evt.pointerId === this.penID) {
this.penID = -1;
let pt = new EventPoint(evt);
// ic.context.lineTo(pt.rawPosition.x, pt.rawPosition.y);
// ic.context.stroke();
this.context.closePath();
this.renderAllStrokes();
evt.returnValue = false;
}
return false;
}
// We treat the event of the pen leaving the canvas as the same as the pen lifting;
// it completes the stroke.
public handlePointerOut(evt) {
if (evt.pointerId === this.penID) {
let pt = new EventPoint(evt);
this.context.lineTo(pt.rawPosition.x, pt.rawPosition.y);
this.context.stroke();
this.context.closePath();
this.penID = -1;
this.renderAllStrokes();
public restoreMode() {
}
return false;
}
public handleTap(evt) {
// Anchor and clear any current selection.
if (this.anySelected()) {
this.anchorSelection();
this.renderAllStrokes();
}
return false;
}
public clear() {
if (!this.anySelected()) {
this.selectAll();
this.inkMode();
public renderAllStrokes() {
}
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
public anchorSelection() {
}
this.renderAllStrokes();
utils.displayStatus("");
utils.displayError("");
}
public selectAll() {
}
public inkMode() {
}
public inkColor() {
}
public undo() {
}
public redo() {
}
// tslint:enable:no-empty
public anySelected(): boolean {
return false;
}
// We will accept pen down or mouse left down as the start of a stroke.
// We will accept touch down or mouse right down as the start of a touch.
public handlePointerDown(evt) {
this.penID = evt.pointerId;
if (evt.pointerType === "touch") {
// ic.gesture.addPointer(evt.pointerId);
}
if ((evt.pointerType === "pen") || ((evt.pointerType === "mouse") && (evt.button === 0))) {
// Anchor and clear any current selection.
this.anchorSelection();
let pt = new EventPoint(evt);
if (pt.properties.isEraser) { // The back side of a pen, which we treat as an eraser
this.tempEraseMode();
} else {
this.restoreMode();
}
this.context.beginPath();
this.context.moveTo(pt.rawPosition.x, pt.rawPosition.y);
let pressureWidth = evt.pressure * 15;
this.context.lineWidth = pressureWidth;
evt.returnValue = false;
}
}
public handlePointerMove(evt) {
if (evt.pointerId === this.penID) {
let pt = new EventPoint(evt);
let w = 8;
let h = 8;
if (evt.pointerType === "touch") {
this.context.strokeStyle = "gray";
w = evt.width;
h = evt.height;
// context.strokeRect(evt.x - w/2 - 1, evt.y - h/2 -1 , w+1, h+1);
this.context.clearRect(evt.x - w / 4, evt.y - h / 4, w / 2, h / 2);
evt.returnValue = false;
return false; // we"re going to clearRect instead
}
if (evt.pointerType === "pen") {
this.context.strokeStyle = "rgba(0, 50, 0, 1)";
w = w * (0.1 + evt.pressure);
h = h * (0.1 + evt.pressure);
} else { // just mouse
this.context.strokeStyle = "rgba(250, 0, 0, 0.5)";
}
this.context.lineWidth = w;
this.context.lineTo(evt.clientX, evt.clientY);
this.context.stroke();
evt.returnValue = false;
// let pts = evt.intermediatePoints;
// for (let i = pts.length - 1; i >= 0 ; i--) {
// }
}
return false;
}
public handlePointerUp(evt) {
if (evt.pointerId === this.penID) {
this.penID = -1;
let pt = new EventPoint(evt);
// ic.context.lineTo(pt.rawPosition.x, pt.rawPosition.y);
// ic.context.stroke();
this.context.closePath();
this.renderAllStrokes();
evt.returnValue = false;
}
return false;
}
// We treat the event of the pen leaving the canvas as the same as the pen lifting;
// it completes the stroke.
public handlePointerOut(evt) {
if (evt.pointerId === this.penID) {
let pt = new EventPoint(evt);
this.context.lineTo(pt.rawPosition.x, pt.rawPosition.y);
this.context.stroke();
this.context.closePath();
this.penID = -1;
this.renderAllStrokes();
}
return false;
}
public handleTap(evt) {
// Anchor and clear any current selection.
if (this.anySelected()) {
this.anchorSelection();
this.renderAllStrokes();
}
return false;
}
public clear() {
if (!this.anySelected()) {
this.selectAll();
this.inkMode();
}
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.renderAllStrokes();
utils.displayStatus("");
utils.displayError("");
}
/**
* Clears the canvas
*/
private clearCanvas() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
private redraw() {
this.clearCanvas();
}
/**
* Resizes the canvas
*/
private resize(width: number, height: number) {
// Updates the size of the canvas
this.canvas.width = width;
this.canvas.height = height;
// And then redraw the canvas
this.redraw();
}
}

111
server/src/canvas/mix.ts Normal file
Просмотреть файл

@ -0,0 +1,111 @@
// private clearCanvas() {
// this._context.clearRect(0, 0, this._width, this._height);
// }
// private draw() {
// //nothing to do if we are already drawing
// if (this._drawing || !this._active || this._index >= this._inkData.length) return;
// this._drawing = true;
// var strokeTime = this._inkData[this._index].t;
// //draw MixInk until we reach lesson time
// while (strokeTime <= this._currentTime && this._index < this._inkData.length) {
// this.processAction();
// if (++this._index >= this._inkData.length) {
// //MixInking finished
// this._drawing = false;
// //this.stop();
// return;
// }
// strokeTime = this._inkData[this._index].t;
// }
// this._drawing = false;
// }
// /***
// * processes the MixInk action from MixInk timeline for current index
// * returns: false if the MixInk has ended or doesn't need to be processed, true otherwise
// */
// private processAction() {
// var action = this._inkData[this._index];
// // Prepare pen
// this.updatePen(action.p, action.k === MixPlayerModels.MixInkActionKind.Draw);
// if (!this._pen) {
// this._logger.warn("MixInk.pen is not set on processAction");
// // bad pen data.
// return;
// }
// var shapes: Array<MixInk.IShape>;
// var scaledDrawPoint: MixInk.IPoint;
// var stylusPoint: MixInk.IStylusPoint;
// if (this._pen.b === MixPlayerModels.MixInkBlush.Highlighter) {
// var scaledWidth = Math.max(1, this._pen.w * this._scaleX);
// var scaledHeight = Math.max(2, this._pen.h * this._scaleY);
// scaledDrawPoint = { x: this._scaleX * action.x, y: this._scaleY * action.y };
// stylusPoint = new MixInk.StylusPoint(scaledDrawPoint, 1, scaledWidth, scaledHeight);
// //process MixInk action as per the kind
// switch (action.k) {
// case MixPlayerModels.MixInkActionKind.Draw:
// shapes = this.getHighliterShapes(this._lastStylusPoint, stylusPoint, false);
// this._lastStylusPoint = stylusPoint;
// break;
// case MixPlayerModels.MixInkActionKind.Move:
// shapes = this.getHighliterShapes(stylusPoint, stylusPoint, true);
// this._lastStylusPoint = stylusPoint;
// break;
// case MixPlayerModels.MixInkActionKind.Clear:
// this.clearCanvas();
// this._lastStylusPoint = null;
// break;
// default:
// this._logger.warn("MixInk.unsupported MixInk action. " + action.k);
// break;
// }
// } else {
// var scaledThickness = Math.max(1, this._pen.th * Math.max(0.5, this._scaleX));
// scaledDrawPoint = { x: this._scaleX * action.x, y: this._scaleY * action.y };
// stylusPoint = new MixInk.StylusPoint(
// scaledDrawPoint, scaledThickness,
// MixInkPlayer.defaultHighlighterTipWidth, MixInkPlayer.defaultHighlighterTipHeight);
// //process MixInk action as per the kind
// switch (action.k) {
// case MixPlayerModels.MixInkActionKind.Draw:
// shapes = this.getShapes(this._lastStylusPoint, stylusPoint, SegmentCircleInclusive.End);
// this._lastStylusPoint = stylusPoint;
// break;
// case MixPlayerModels.MixInkActionKind.Move:
// shapes = this.getShapes(stylusPoint, stylusPoint, SegmentCircleInclusive.End);
// this._lastStylusPoint = stylusPoint;
// break;
// case MixPlayerModels.MixInkActionKind.Clear:
// //clear the canvas
// this.clearCanvas();
// this._lastStylusPoint = null;
// break;
// default:
// this._logger.warn("MixInk.unsupported MixInk action. " + action.k);
// break;
// }
// }
// // Render shapes if there is any
// if (shapes) {
// shapes.forEach((item: MixInk.IShape) => {
// this._context.beginPath();
// item.render(this._context);
// this._context.closePath();
// this._context.fill();
// });
// }
// }

Просмотреть файл

@ -53,7 +53,7 @@ export default class StickyNote {
}
public manipulateElement(e) {
// Uncomment the following code if you want to disable the built-in inertia
// Uncomment the following code if you want to disable the built-in inertia
// provided by dynamic gesture recognition
// if (false && (e.detail == e.MSGESTURE_FLAG_INERTIA))
@ -61,10 +61,10 @@ export default class StickyNote {
// manipulate only with touch
if (1 || e.pointerType === "touch") {
// Get the latest CSS transform on the element
// Get the latest CSS transform on the element
let m;
// Get the latest CSS transform on the element in MS Edge
// Get the latest CSS transform on the element in MS Edge
m = new WebKitCSSMatrix(window.getComputedStyle(this.gesture.target, null).transform);
if (m) {

Просмотреть файл

@ -141,3 +141,23 @@ export function parseURL(url) {
source: url,
};
}
// Following recomendations of https://developer.mozilla.org/en-US/docs/Web/Events/resize to
// throttle computationally expensive events
export function throttle(type: string, name: string, obj?: any) {
obj = obj || window;
let running = false;
obj.addEventListener(
type,
() => {
if (running) {
return;
}
running = true;
requestAnimationFrame(() => {
obj.dispatchEvent(new CustomEvent(name));
running = false;
});
});
};

Просмотреть файл

@ -70,7 +70,7 @@ function _inherits(subClass, superClass) {
}
}
// tslint:disable:only-arrow-functions:simplify to work around es6 classes to typescript difficulties
// tslint:disable:only-arrow-functions
// tslint:disable-next-line:variable-name
let VideoBlot: any = function (_BlockEmbed3) {
// tslint:disable-next-line:no-var-keyword no-shadowed-variable
@ -126,7 +126,7 @@ let host = new ivy.Host({
secret: "IvyBearerToken",
});
// tslint:disable:only-arrow-functions:simplify to work around es6 classes to typescript difficulties
// tslint:disable:only-arrow-functions
// tslint:disable-next-line:variable-name
let ChartBlot: any = function (_BlockEmbed3) {
// tslint:disable-next-line:no-var-keyword no-shadowed-variable
@ -220,7 +220,7 @@ export function connect(id: string, sync: boolean) {
let range = quill.getSelection(true);
quill.insertText(range.index, "\n", Quill.sources.USER);
// Disable rules for simplicity with Ivy input format
// Disable rules for simplicity with Ivy input format
let chartDef = {
chartTitleEdge: 1,
chartTitlePosition: 1,

Просмотреть файл

@ -72,7 +72,7 @@ class TableService implements ITableService {
templateUrl: "templates/document.component.html",
})
export class DocumentComponent implements OnInit {
// Loading flag for the document
// Loading flag for the document
public loaded: boolean = false;
public url: string;

Просмотреть файл

@ -17,7 +17,7 @@ export class InteractiveDocumentFrameComponent implements AfterViewInit {
}
public ngAfterViewInit() {
// Load in the bound view
// Load in the bound view
let iframe = this.elementRef.nativeElement.querySelector("iframe");
iframe.setAttribute("src", this.url);
}

Просмотреть файл

@ -1,4 +1,4 @@
// The require here is deliberate. The TypeScript browserify will elide this line if
// The require here is deliberate. The TypeScript browserify will elide this line if
// a standard import given no modules are used. We are including the polyfills so we pick
// them up with our browserify package.

Просмотреть файл

@ -80,7 +80,7 @@ export class PostMessageHost implements IPostMessageHost {
* Client is requesting to connect to the server
*/
private processConnect(event: MessageEvent, message: IPacket): void {
// Ignore connection events if we aren"t listening
// Ignore connection events if we aren"t listening
if (!this.connectionCallback) {
// tslint:disable-next-line:no-console
console.log("Client is attempting to connect but the server is not listening");
@ -106,7 +106,7 @@ export class PostMessageHost implements IPostMessageHost {
}
/**
* Retrieves a new number to represent a connection
* Retrieves a new number to represent a connection
*/
private getConnectionId(): number {
return this.nextConnectionId++;

Просмотреть файл

@ -55,7 +55,7 @@ export class PostMessageSocket implements IPostMessageSocket {
public processMessageReceipt(message: IMessage) {
// reject the message if no listener is defined.
// Alternatively if needed we could buffer messages until one is defined. But the former is simpler.
// Alternatively if needed we could buffer messages until one is defined. But the former is simpler.
if (!this.listener) {
this.postMessage(MessageType.Failure, { message: "No handler defined" });
return;

Просмотреть файл

@ -61,7 +61,7 @@ router.get("/", (req: express.Request, response: express.Response) => {
if (error) {
return reject(error);
} else {
// MSFT strings are in UTC but don"t place the UTC marker in the date string -
// MSFT strings are in UTC but don"t place the UTC marker in the date string -
// convert to this format to standardize the input to CalendarEvent
let microsoftResults: ICalendarEvent[] = body.value.map((item) => {
let loc = item.location ? item.location.displayName : "";
@ -136,7 +136,8 @@ router.get("/", (req: express.Request, response: express.Response) => {
});
router.delete("/:provider/:id", (req: express.Request, response: express.Response) => {
// tslint:disable:no-string-literal:easier access to param data
// easier access to param data
// tslint:disable:no-string-literal
let provider = req.params["provider"];
let eventId = req.params["id"];
// tslint:enable:no-string-literal

Просмотреть файл

@ -3,7 +3,8 @@ import * as passport from "passport";
import * as accounts from "../accounts";
import * as authOptions from "./authOptions";
// tslint:disable-next-line:no-var-requires:simpler code path and module not setup for import
// simpler code path and module not setup for import
// tslint:disable-next-line:no-var-requires
let ensureLoggedIn = require("connect-ensure-login").ensureLoggedIn;
let router = express.Router();

Просмотреть файл

@ -8,8 +8,8 @@ import * as request from "request";
import * as accounts from "../accounts";
import { defaultPartials } from "./partials";
// tslint:disable:no-console:Server side code
// tslint:disable:max-line-length:TODO split get into helper functions
// tslint:disable:no-console
// tslint:disable:max-line-length
let router = express.Router();

Просмотреть файл

@ -1,7 +1,8 @@
import * as express from "express";
import { defaultPartials } from "./partials";
// tslint:disable-next-line:no-var-requires:simpler code path and module not setup for import
// simpler code path and module not setup for import
// tslint:disable-next-line:no-var-requires
let ensureLoggedIn = require("connect-ensure-login").ensureLoggedIn;
let router = express.Router();

Просмотреть файл

@ -3,7 +3,8 @@ import * as _ from "lodash";
import { IUser } from "../accounts";
import { defaultPartials } from "./partials";
// tslint:disable-next-line:no-var-requires:simpler code path and module not setup for import
// simpler code path and module not setup for import
// tslint:disable-next-line:no-var-requires
let ensureLoggedIn = require("connect-ensure-login").ensureLoggedIn;
let router = express.Router();

Просмотреть файл

@ -15,7 +15,7 @@ class View implements IView {
}
class Views implements IViews {
// tslint:disable:variable-name:JSON format contains _
// tslint:disable:variable-name
public _links: { [rel: string]: ILink | ILink[] };
public _embedded: { [rel: string]: View[] };
// tslint:enable:variable-name