From 8659f997228be133e2633ad3086bb5e5b4e71c07 Mon Sep 17 00:00:00 2001 From: Lily Wang Date: Sun, 5 May 2019 22:48:35 +1000 Subject: [PATCH 01/16] added selection behaviour --- src/component/representation-element.ts | 13 ++ src/component/structure-component.ts | 34 +++- src/controls/mouse-actions.ts | 100 +++++++++- src/controls/picking-controls.ts | 22 +++ src/geometry/shape-2d.ts | 240 ++++++++++++++++++++++++ src/proxy/bond-proxy.ts | 7 + src/stage/mouse-observer.ts | 21 +++ src/stage/selecting-behavior.ts | 50 +++++ src/stage/stage.ts | 5 + src/utils/toggle-set.ts | 48 +++++ src/viewer/viewer.ts | 75 ++++++++ 11 files changed, 612 insertions(+), 3 deletions(-) create mode 100644 src/geometry/shape-2d.ts create mode 100644 src/stage/selecting-behavior.ts create mode 100644 src/utils/toggle-set.ts diff --git a/src/component/representation-element.ts b/src/component/representation-element.ts index 915200c39..38f400a49 100644 --- a/src/component/representation-element.ts +++ b/src/component/representation-element.ts @@ -154,6 +154,19 @@ class RepresentationElement extends Element { return this } + /** + * Set selected atoms via indices + * @param {number[]} indices array of selected atom indices + * @return {RepresentationElement} this object + */ + setSelectedAtomIndices (indices: number[]) { + if (indices) { + return this.setSelection('@'+indices.join()) + } else { + return this.setSelection('none') + } + } + /** * Set representation parameters * @param {RepresentationParameters} params - parameter object diff --git a/src/component/structure-component.ts b/src/component/structure-component.ts index f581c0a19..6e5058af2 100644 --- a/src/component/structure-component.ts +++ b/src/component/structure-component.ts @@ -25,11 +25,12 @@ import Stage from '../stage/stage' import StructureRepresentation from '../representation/structure-representation' import AtomProxy from '../proxy/atom-proxy' import { Vector3, Box3 } from 'three'; +import { createToggleSet, ToggleSet } from '../utils/toggle-set'; export type StructureRepresentationType = ( 'angle'|'axes'|'backbone'|'ball+stick'|'base'|'cartoon'|'contact'|'dihedral'| 'distance'|'helixorient'|'hyperball'|'label'|'licorice'|'line'|'surface'| - 'ribbon'|'rocket'|'rope'|'spacefill'|'trace'|'tube'|'unitcell' + 'ribbon'|'rocket'|'rope'|'selected'|'spacefill'|'trace'|'tube'|'unitcell' ) export const StructureComponentDefaultParameters = Object.assign({ @@ -66,11 +67,13 @@ class StructureComponent extends Component { pickBuffer: RingBuffer pickDict: SimpleDict lastPick?: number + selectedAtomIndices: ToggleSet spacefillRepresentation: RepresentationElement distanceRepresentation: RepresentationElement angleRepresentation: RepresentationElement dihedralRepresentation: RepresentationElement + selectedRepresentation: RepresentationElement measureRepresentations: RepresentationCollection @@ -89,6 +92,7 @@ class StructureComponent extends Component { this.pickBuffer = createRingBuffer(4) this.pickDict = createSimpleDict() + this.selectedAtomIndices = createToggleSet() this.spacefillRepresentation = this.addRepresentation('spacefill', { sele: 'none', @@ -107,6 +111,9 @@ class StructureComponent extends Component { this.dihedralRepresentation = this.addRepresentation( 'dihedral', MeasurementDefaultParams, true ) + this.selectedRepresentation = this.addRepresentation( + 'selected', MeasurementDefaultParams, true + ) this.measureRepresentations = new RepresentationCollection([ this.spacefillRepresentation, @@ -174,13 +181,14 @@ class StructureComponent extends Component { * @return {undefined} */ setDefaultAssembly (value:string) { - // filter out non-exsisting assemblies + // filter out non-existing assemblies if (this.structure.biomolDict[value] === undefined) value = '' // only set default assembly when changed if (this.parameters.defaultAssembly !== value) { const reprParams = { defaultAssembly: value } this.reprList.forEach(repr => repr.setParameters(reprParams)) this.measureRepresentations.setParameters(reprParams) + this.selectedRepresentation.setParameters(reprParams) this.parameters.defaultAssembly = value this.signals.defaultAssemblyChanged.dispatch(value) } @@ -196,6 +204,7 @@ class StructureComponent extends Component { repr.build() }) this.measureRepresentations.build() + this.selectedRepresentation.build() } /** @@ -211,6 +220,7 @@ class StructureComponent extends Component { updateRepresentations (what: any) { super.updateRepresentations(what) this.measureRepresentations.update(what) + this.selectedRepresentation.update(what) } addRepresentation (type: StructureRepresentationType, params: { [k: string]: any } = {}, hidden = false) { @@ -258,6 +268,7 @@ class StructureComponent extends Component { this.trajList.length = 0 this.structure.dispose() this.measureRepresentations.dispose() + this.selectedRepresentation.dispose() super.dispose() } @@ -431,6 +442,25 @@ class StructureComponent extends Component { } this.measureBuild() } + + selectedPick (atoms: AtomProxy[]) { + var atomIndices = atoms.map(x => x.index) + this.selectedAtomIndices.toggleAny(atomIndices) + this.selectedUpdate() + } + + selectedUpdate () { + const pickData = this.selectedAtomIndices.list + const radiusData: { [k: number]: number } = {} + pickData.forEach(ai => { + const r = Math.max(0.1, this.getMaxRepresentationRadius(ai)) + radiusData[ ai ] = r * (2.3 - smoothstep(0.1, 2, r)) + }) + this.spacefillRepresentation.setSelection( + pickData.length ? ( '@' + pickData.join(',') ) : 'none' + ) + this.spacefillRepresentation.setParameters({ radiusData }) + } } export const enum MeasurementFlags { diff --git a/src/controls/mouse-actions.ts b/src/controls/mouse-actions.ts index 4c155ddd8..00931bae4 100644 --- a/src/controls/mouse-actions.ts +++ b/src/controls/mouse-actions.ts @@ -9,6 +9,7 @@ import { almostIdentity } from '../math/math-utils' import Stage from '../stage/stage' import StructureComponent from '../component/structure-component' import SurfaceRepresentation from '../representation/surface-representation' +import AtomProxy from '../proxy/atom-proxy'; export type ScrollCallback = (stage: Stage, delta: number) => void export type DragCallback = (stage: Stage, dx: number, dy: number) => void @@ -176,6 +177,35 @@ class MouseActions { stage.trackballControls.rotateComponent(dx, dy) } + static drawDragBox (stage: Stage, dx: number, dy: number) { + + } + + static updateDragBox (stage: Stage, dx: number, dy: number) { + + } + /** + * Move picked component based on mouse coordinate changes + * @param {Stage} stage + * @param {Number} dx - amount to move in x direction + * @param {Number} dy - amount to move in y direction + * @return {undefined} + */ + static moveComponentDrag (stage: Stage, dx: number, dy: number) { + return; // TODO** + } + + /** + * Pick component based on mouse coordinate changes + * @param {Stage} stage + * @param {Number} dx - amount to select in x direction + * @param {Number} dy - amount to select in y direction + * @return {undefined} + */ + static lassoComponentDrag (stage: Stage, dx: number, dy: number) { + return; // TODO** + } + /** * Move picked element to the center of the screen * @param {Stage} stage - the stage @@ -217,6 +247,54 @@ class MouseActions { stage.measureClear() } } + + /** + * Add pick + * @param {Stage} stage - the stage + * @param {PickingProxy} pickingProxy - the picking data object + * @return {undefined} + */ + static selectPick (stage: Stage, pickingProxy: PickingProxy) { + if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) { + const atoms = [pickingProxy.atom] || pickingProxy.bond.atoms + const sc = pickingProxy.component as StructureComponent + sc.selectedPick(atoms) + } + } + + static selectPickAll (stage: Stage, pickingProxies: PickingProxy[]) { + let components: StructureComponent[] = [] + let picked: AtomProxy[][] = [] + + pickingProxies.forEach(function (pickingProxy) { + if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) { + let atoms = [pickingProxy.atom] || pickingProxy.bond.atoms + let sc = pickingProxy.component as StructureComponent + + if (!components.includes(sc)) { + let _new: AtomProxy[] = [] + components.push(sc) + picked.push(_new) + } + + let j = components.indexOf(sc) + atoms.forEach(function (a) { + if (!picked[j].includes(a)) picked[j].push(a) + }) + } + }) + + for (var i = 0; i < components.length; i++) { + components[i].selectedPick(picked[i]) + } + } + + static clearSelect (stage: Stage) { + stage.eachComponent(function (sc: StructureComponent) { + sc.selectedAtomIndices.clear() + }, "structure") + } + } type MouseActionPreset = [ string, MouseActionCallback ][] @@ -271,7 +349,27 @@ export const MouseActionPresets = { [ 'scroll', MouseActions.focusScroll ], [ 'clickPick-middle', MouseActions.movePick ], [ 'hoverPick', MouseActions.tooltipPick ] - ] as MouseActionPreset + ] as MouseActionPreset, + iqmol: [ + [ 'scroll', MouseActions.zoomScroll ], + // [ 'scroll-shift', MouseActions.focusScroll ], + // [ 'scroll-ctrl', MouseActions.isolevelScroll ], + // [ 'scroll-shift-ctrl', MouseActions.zoomFocusScroll ], + + [ 'drag-left', MouseActions.rotateDrag ], + [ 'drag-right', MouseActions.panDrag ], + [ 'drag-ctrl-left', MouseActions.rotatePositionComponentDrag ], + [ 'drag-ctrl-right', MouseActions.moveComponentDrag ], + [ 'drag-shift-left', MouseActions.selectPickAll ], + [ 'drag-middle', MouseActions.zoomFocusDrag ], + + [ 'clickPick-shift-left', MouseActions.selectPick ], + [ 'doubleClick-shift-left', MouseActions.clearSelect], + + [ 'clickPick-right', MouseActions.measurePick ], + [ 'clickPick-middle', MouseActions.movePick ], + [ 'hoverPick', MouseActions.tooltipPick ] + ] } export default MouseActions diff --git a/src/controls/picking-controls.ts b/src/controls/picking-controls.ts index bccf4423d..32c90dabe 100644 --- a/src/controls/picking-controls.ts +++ b/src/controls/picking-controls.ts @@ -39,6 +39,28 @@ class PickingControls { } } } + + pickAll (x0: number, y0: number, dx: number, dy: number) { + const pickedData = this.viewer.pickAll(x0, y0, dx, dy) + let picked = [] + + for (var i = 0; i < pickedData.length; i++) { + let pickingData = pickedData[i] + if (pickingData.picker && + pickingData.picker.type !== 'ignore' && + pickingData.pid !== undefined + ) { + let pickerArray = pickingData.picker.array + if (pickerArray && pickingData.pid >= pickerArray.length) { + console.error('pid >= picker.array.length') + } else { + picked.push( new PickingProxy(pickingData, this.stage) ) + } + } + } + + return picked + } } export default PickingControls diff --git a/src/geometry/shape-2d.ts b/src/geometry/shape-2d.ts new file mode 100644 index 000000000..bd51b1bff --- /dev/null +++ b/src/geometry/shape-2d.ts @@ -0,0 +1,240 @@ +/** + * @file Shape-2D + * @author Lily Wang + * @private + */ + + +import { Box2, Vector2, Color } from 'three' + +import { createParams, ensureFloat32Array, getUintArray } from '../utils' +import { + ArrowPrimitive, BoxPrimitive, ConePrimitive, CylinderPrimitive, EllipsoidPrimitive, + OctahedronPrimitive, SpherePrimitive, TetrahedronPrimitive, TextPrimitive, + TorusPrimitive, PointPrimitive, WidelinePrimitive +} from './primitive' +import { MeshPicker } from '../utils/picker' +import Buffer from '../buffer/buffer' +import MeshBuffer from '../buffer/mesh-buffer' +import { TextBufferParameters } from '../buffer/text-buffer' + +const tmpBox = new Box3() + +const Primitives = [ + ArrowPrimitive, BoxPrimitive, ConePrimitive, CylinderPrimitive, + EllipsoidPrimitive, OctahedronPrimitive, SpherePrimitive, TetrahedronPrimitive, + TextPrimitive, TorusPrimitive, PointPrimitive, WidelinePrimitive +] + +export const ShapeDefaultParameters = { + aspectRatio: 1.5, + sphereDetail: 2, + radialSegments: 50, + disableImpostor: false, + openEnded: false, + dashedCylinder: false, + labelParams: {} as Partial, + pointSize: 2, + sizeAttenuation: false, + useTexture: true, + lineWidth: 2 +} +export type ShapeParameters = typeof ShapeDefaultParameters + +/** + * Class for building custom shapes. + * + * @example + * var shape = new NGL.Shape('shape', { disableImpostor: true }); + * shape.addSphere([ 0, 0, 9 ], [ 1, 0, 0 ], 1.5 ); + * shape.addEllipsoid([ 6, 0, 0 ], [ 1, 0, 0 ], 1.5, [ 3, 0, 0 ], [ 0, 2, 0 ]); + * shape.addCylinder([ 0, 2, 7 ], [ 0, 0, 9 ], [ 1, 1, 0 ], 0.5); + * shape.addCone([ 0, 2, 7 ], [ 0, 3, 3 ], [ 1, 1, 0 ], 1.5); + * shape.addArrow([ 1, 2, 7 ], [ 30, 3, 3 ], [ 1, 0, 1 ], 1.0); + * shape.addBox([ 0, 3, 0 ], [ 1, 0, 1 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]); + * var shapeComp = stage.addComponentFromObject(shape); + * geoComp.addRepresentation('buffer'); + */ +class Shape { + name: string + parameters: ShapeParameters + + boundingBox = new Box2() + bufferList: Buffer[] = [] + meshCount = 0 + + _origin?: Vector2 + _primitiveData: { [k: string]: any } = {} + + /** + * @param {String} name - name + * @param {Object} params - parameter object + * @param {Integer} params.aspectRatio - arrow aspect ratio, used for cylinder radius and cone length + * @param {Integer} params.sphereDetail - sphere quality (icosahedron subdivisions) + * @param {Integer} params.radialSegments - cylinder quality (number of segments) + * @param {Boolean} params.disableImpostor - disable use of raycasted impostors for rendering + * @param {Boolean} params.openEnded - capped or not + * @param {TextBufferParameters} params.labelParams - label parameters + */ + constructor (name = 'shape', params: Partial = {}) { + this.name = name + + this.parameters = createParams(params, ShapeDefaultParameters) + + Primitives.forEach(P => { + Object.keys(P.fields).forEach(name => { + this._primitiveData[ P.getShapeKey(name) ] = [] + }) + this._primitiveData[ P.getShapeKey('name') ] = [] + }) + } + + /** + * Add a buffer + * @param {Buffer} buffer - buffer object + * @return {Shape} this object + */ + addBuffer (buffer: Buffer) { + this.bufferList.push(buffer) + + const geometry = (buffer as any).geometry // TODO + if (!geometry.boundingBox) { + geometry.computeBoundingBox() + } + this.boundingBox.union(geometry.boundingBox) + + return this + } + + /** + * Add a mesh + * @example + * shape.addMesh( + * [ 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1 ], + * [ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 ] + * ); + * + * @param {Float32Array|Array} position - positions + * @param {Float32Array|Array} color - colors + * @param {Uint32Array|Uint16Array|Array} [index] - indices + * @param {Float32Array|Array} [normal] - normals + * @param {String} [name] - text + * @return {Shape} this object + */ + addMesh (position: Float32Array|number[], color:Float32Array|number[], index: Uint32Array|Uint16Array|number[], normal: Float32Array|number[], name?: string) { + position = ensureFloat32Array(position) + color = ensureFloat32Array(color) + if (Array.isArray(index)) { + index = getUintArray(index, position.length) + } + if (normal) { + normal = ensureFloat32Array(normal) + } + + const data = { position, color, index, normal } + + + tmpBox.setFromArray(position) + this.boundingBox.union(tmpBox) + this.meshCount += 1 + + return this + } + + /** + * Add a sphere + * @example + * shape.addSphere([ 0, 0, 9 ], [ 1, 0, 0 ], 1.5); + * + * @param {Vector3|Array} position - position vector or array + * @param {Color|Array} color - color object or array + * @param {Float} radius - radius value + * @param {String} [name] - text + * @return {Shape} this object + */ + addSphere (position: Vector3|[number, number, number], color: Color|[number, number, number], radius: number, name: string) { + SpherePrimitive.objectToShape( + this, { position, color, radius, name } + ) + return this + } + + + + /** + * Add a box + * @example + * shape.addBox([ 0, 3, 0 ], [ 1, 0, 1 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]); + * + * @param {Vector3|Array} position - position vector or array + * @param {Color|Array} color - color object or array + * @param {Float} size - size value + * @param {Vector3|Array} heightAxis - height axis vector or array + * @param {Vector3|Array} depthAxis - depth axis vector or array + * @param {String} [name] - text + * @return {Shape} this object + */ + addBox (position: Vector3|[number, number, number], color: Color|[number, number, number], size: number, heightAxis: Vector3|[number, number, number], depthAxis: Vector3|[number, number, number], name: string) { + BoxPrimitive.objectToShape( + this, { position, color, size, heightAxis, depthAxis, name } + ) + return this + } + + + /** + * Add point + * @example + * shape.addPoint([ 10, -2, 4 ], [ 0.2, 0.5, 0.8 ]); + * + * @param {Vector3|Array} position - position vector or array + * @param {Color|Array} color - color object or array + * @param {String} [name] - text + * @return {Shape} this object + */ + addPoint (position: Vector3|[number, number, number], color: Color|[number, number, number], name: string) { + PointPrimitive.objectToShape( + this, { position, color, name } + ) + return this + } + + + + getBufferList () { + const buffers: Buffer[] = [] + + Primitives.forEach(P => { + if (this._primitiveData[ P.getShapeKey('color') ].length) { + buffers.push(P.bufferFromShape(this, this.parameters)) + } + }) + + return this.bufferList.concat(buffers) + } + + dispose () { + this.bufferList.forEach(function (buffer) { + buffer.dispose() + }) + this.bufferList.length = 0 + + Primitives.forEach(P => { + Object.keys(P.fields).forEach(name => { + this._primitiveData[ P.getShapeKey(name) ].length = 0 + }) + this._primitiveData[ P.getShapeKey('name') ].length = 0 + }) + } + + get origin () { + if (!this._origin) { + this._origin = this.boundingBox.getOrigin(new Vector2()) + } + return this._origin + } + + get type () { return 'Shape' } +} + +export default Shape diff --git a/src/proxy/bond-proxy.ts b/src/proxy/bond-proxy.ts index e380d9194..d1471f822 100644 --- a/src/proxy/bond-proxy.ts +++ b/src/proxy/bond-proxy.ts @@ -53,6 +53,13 @@ class BondProxy { return this.structure.getAtomProxy(this.atomIndex2) } + /** + * @type {[AtomProxy, AtomProxy]} + */ + get atoms () { + return [this.atom1, this.atom2] + } + /** * @type {Integer} */ diff --git a/src/stage/mouse-observer.ts b/src/stage/mouse-observer.ts index 5b2ab4894..3939e2960 100644 --- a/src/stage/mouse-observer.ts +++ b/src/stage/mouse-observer.ts @@ -62,6 +62,7 @@ export interface MouseSignals { moved: Signal // on move: deltaX, deltaY scrolled: Signal // on scroll: delta dragged: Signal // on drag: deltaX, deltaY + draggedXY: Signal //on drag: x0, y0, x1, y1 dropped: Signal // on drop clicked: Signal // on click hovered: Signal // on hover @@ -106,6 +107,7 @@ class MouseObserver { moved: new Signal(), scrolled: new Signal(), dragged: new Signal(), + draggedXY: new Signal(), dropped: new Signal(), clicked: new Signal(), hovered: new Signal(), @@ -256,6 +258,7 @@ class MouseObserver { * handle mouse move * @emits {MouseSignals.moved} when moved * @emits {MouseSignals.dragged} when dragged + * @emits {MouseSignals.draggedXY} when dragged * @param {Event} event - mouse event * @return {undefined} */ @@ -278,6 +281,12 @@ class MouseObserver { this.signals.moved.dispatch(dx, dy) if (this.pressed) { this.signals.dragged.dispatch(dx, dy) + this.signals.draggedXY.dispatch( + this.prevPosition.x, + this.prevPosition.y, + this.position.x, + this.position.y + ) } } @@ -405,6 +414,12 @@ class MouseObserver { this.signals.moved.dispatch(dx, dy) if (this.pressed) { this.signals.dragged.dispatch(dx, dy) + this.signals.draggedXY.dispatch( + this.prevPosition.x, + this.prevPosition.y, + this.position.x, + this.position.y + ) } break } @@ -432,6 +447,12 @@ class MouseObserver { this.signals.moved.dispatch(dx, dy) if (this.pressed) { this.signals.dragged.dispatch(dx, dy) + this.signals.draggedXY.dispatch( + this.prevPosition.x, + this.prevPosition.y, + this.position.x, + this.position.y + ) } } } diff --git a/src/stage/selecting-behavior.ts b/src/stage/selecting-behavior.ts new file mode 100644 index 000000000..3a60a38e9 --- /dev/null +++ b/src/stage/selecting-behavior.ts @@ -0,0 +1,50 @@ +/** + * @file Selecting Behavior + * @author Lily Wang + * @private + */ + +import Stage from './stage' +import MouseObserver from './mouse-observer' +import Viewer from '../viewer/viewer' +import MouseControls from '../controls/mouse-controls' + +class PickingBehavior { + viewer: Viewer + mouse: MouseObserver + controls: MouseControls + + constructor (readonly stage: Stage) { + this.stage = stage + this.mouse = stage.mouseObserver + this.controls = stage.mouseControls + + this.mouse.signals.clicked.add(this._onClick, this) + this.mouse.signals.dragged.add(this._onDragXY, this) + this.mouse.signals.doubleClicked.add(this._onDoubleClick, this) + } + + _onClick (x: number, y: number) { + const pickingProxy = this.stage.pickingControls.pick(x, y) + this.stage.signals.clicked.dispatch(pickingProxy) + this.controls.run('clickPick', pickingProxy) + } + + _onDragXY (x0: number, y0: number, x1: number, y1: number) { + const pickedProxies = this.stage.pickingControls.pickAll(x0, y0, x1-x0, y1-y0) + this.controls.run('select') + + + } + + _onMouseDown (x: number, y: number) { + + } + + dispose () { + this.mouse.signals.clicked.remove(this._onClick, this) + this.mouse.signals.hovered.remove(this._onHover, this) + } +} + +export default PickingBehavior diff --git a/src/stage/stage.ts b/src/stage/stage.ts index 57741a1ce..edafb4109 100644 --- a/src/stage/stage.ts +++ b/src/stage/stage.ts @@ -899,6 +899,11 @@ class Stage { this.eachComponent((sc: StructureComponent) => sc.measureUpdate(), 'structure') } + selectedUpdate () { + this.eachComponent((sc: StructureComponent) => sc.selectedUpdate(), 'structure') + } + + /** * Cleanup when disposing of a stage object */ diff --git a/src/utils/toggle-set.ts b/src/utils/toggle-set.ts new file mode 100644 index 000000000..0d860ca1c --- /dev/null +++ b/src/utils/toggle-set.ts @@ -0,0 +1,48 @@ +import value from "*.frag"; + +/** + * @file Queue + * @author Lily Wang + * @private + */ + + export interface ToggleSet { + has: (value: T) => boolean + add: (value: T) => void + del: (value: T) => void + toggle: (value: T) => void + toggleAny: (value: T[]) => void + count: number + list: T[] + clear: () => void +} + +export function createToggleSet (): ToggleSet { + const list: T[] = [] + + return { + has: function (value: T) { return list.indexOf(value) !== -1 }, + add: function (value: T) { if (!this.has(value)) list.push(value); }, + del: function (value: T) { if (this.has(value)) list.splice(list.indexOf(value), 1); }, + toggle: function (value: T) { + if (this.has(value)) { + this.del(value) + } else { + this.add(value) + } + }, + toggleAny: function (values: T[]) { + let addAll = false; + for (var i = 0; i < values.length; i++) { + if (!this.has(values[i])) addAll = true; + } + + if (addAll) values.forEach(this.add); else values.forEach(this.del) + }, + get count () { return list.length }, + get list () {return list}, + clear: function () { + list.splice(0) + } + } +} \ No newline at end of file diff --git a/src/viewer/viewer.ts b/src/viewer/viewer.ts index 368c571f4..6f65629e4 100644 --- a/src/viewer/viewer.ts +++ b/src/viewer/viewer.ts @@ -993,6 +993,81 @@ export default class Viewer { return { pid, instance, picker } } + pickAll (x0: number, y0: number, dx: number, dy: number) { + + if (this.parameters.cameraType === 'stereo') { + // TODO picking broken for stereo camera + return [] + } + + let picked = [] + + x0 *= window.devicePixelRatio + y0 *= window.devicePixelRatio + dx *= window.devicePixelRatio + dy *= window.devicePixelRatio + + let x = Math.min(x0, x0 + dx) + let y = Math.min(y0, y0 + dy) + + let px = Math.abs(dx) + let py = Math.abs(dy) + + let _pixelBufferFloat = new Float32Array(4 * px * py) + let _pixelBufferUint = new Uint8Array(4 * px * py) + const pixelBuffer = SupportsReadPixelsFloat ? _pixelBufferFloat : _pixelBufferUint + + this.render(true) + this.renderer.readRenderTargetPixels( + this.pickingTarget, x, y, px, py, pixelBuffer + ) + + for (let i = 0; i < px*py; i++) { + + let pid = 0, instance, picker + const offset = i * 4 + + const oid = Math.round(pixelBuffer[ offset + 3 ]) + const object = this.pickingGroup.getObjectById(oid) + if (object) { + instance = object.userData.instance + picker = object.userData.buffer.picking + } else { + continue + } + + if (SupportsReadPixelsFloat) { + pid = + ((Math.round(pixelBuffer[offset] * 255) << 16) & 0xFF0000) | + ((Math.round(pixelBuffer[offset + 1] * 255) << 8) & 0x00FF00) | + ((Math.round(pixelBuffer[offset + 2] * 255)) & 0x0000FF) + } else { + pid = + (pixelBuffer[offset] << 16) | + (pixelBuffer[offset + 1] << 8) | + (pixelBuffer[offset + 2]) + } + + picked.push({ pid, instance, picker }) + } + // if( Debug ){ + // const rgba = Array.apply( [], pixelBuffer ); + // Log.log( pixelBuffer ); + // Log.log( + // "picked color", + // rgba.map( c => { return c.toPrecision( 2 ) } ) + // ); + // Log.log( "picked pid", pid ); + // Log.log( "picked oid", oid ); + // Log.log( "picked object", object ); + // Log.log( "picked instance", instance ); + // Log.log( "picked position", x, y ); + // Log.log( "devicePixelRatio", window.devicePixelRatio ); + // } + + return picked + } + requestRender () { if (this.renderPending) { // Log.info("there is still a 'render' call pending") From 5c4c238592ca345ce9d127f047b9a603fe4a0802 Mon Sep 17 00:00:00 2001 From: Lily Wang Date: Mon, 6 May 2019 23:37:15 +1000 Subject: [PATCH 02/16] added drag --- package-lock.json | 7294 ++++++++++++++++++++-------- package.json | 6 +- src/controls/mouse-actions.ts | 47 +- src/controls/trackball-controls.ts | 41 + src/geometry/shape-2d.ts | 240 - src/stage/selecting-behavior.ts | 18 +- src/stage/stage.ts | 16 + src/utils/toggle-set.ts | 4 +- src/viewer/drag-selection.ts | 75 + 9 files changed, 5549 insertions(+), 2192 deletions(-) delete mode 100644 src/geometry/shape-2d.ts create mode 100644 src/viewer/drag-selection.ts diff --git a/package-lock.json b/package-lock.json index ea007bfcb..d058bc2eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,23 +5,144 @@ "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.0.0-beta.56", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.56.tgz", - "integrity": "sha512-OBeGs8UXWpKl0oK2T5nUXNl2yu8RKxqL/7aUnMtKDXCU6VUrNP3npdrPivBA11HPB15TVI49nWf2lntTzoUuAg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/core": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.4.tgz", + "integrity": "sha512-lQgGX3FPRgbz2SKmhMtYgJvVzGZrmjaF4apZ2bLwofAKiSjxU0drPh4S/VasyYXwaTs+A1gvQ45BN8SQJzHsQQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.4", + "@babel/helpers": "^7.4.4", + "@babel/parser": "^7.4.4", + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.11", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", + "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", "dev": true, "requires": { - "@babel/highlight": "7.0.0-beta.56" + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + }, + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/helpers": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz", + "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==", + "dev": true, + "requires": { + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" } }, "@babel/highlight": { - "version": "7.0.0-beta.56", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.56.tgz", - "integrity": "sha512-q4TfI+jJISul6vVpZJktzH4tupwRiVk6KXRhB8PHqJ7erl966I6ePDXl9mAbE8jMM7YswhnnB0j1SYP7LBVyhg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", "dev": true, "requires": { "chalk": "^2.0.0", "esutils": "^2.0.2", - "js-tokens": "^3.0.0" + "js-tokens": "^4.0.0" }, "dependencies": { "ansi-styles": { @@ -34,9 +155,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -44,10 +165,16 @@ "supports-color": "^5.3.0" } }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -55,209 +182,1306 @@ } } }, - "@types/chroma-js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-1.3.5.tgz", - "integrity": "sha512-GyKKeo/SR3FTD1nAuFcxdQ+1JW2E3Fwckto849cfUGvUvlCEuCbPc9zkmVGLp2MYs0fSc5QqLzJVY6VbD3NYMw==", - "dev": true - }, - "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - }, - "@types/events": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", - "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==", + "@babel/parser": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.4.tgz", + "integrity": "sha512-5pCS4mOsL+ANsFZGdvNLybx4wtqAZJ0MJjMHxvzI3bvIsz6sQvzW8XX92EYIkiPtIvcfG3Aj+Ir5VNyjnZhP7w==", "dev": true }, - "@types/fs-extra": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.1.tgz", - "integrity": "sha512-h3wnflb+jMTipvbbZnClgA2BexrT4w0GcfoCz5qyxd0IRsbqhLSyesM6mqZTAnhbVmhyTm5tuxfRu9R+8l+lGw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/glob": { - "version": "5.0.35", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.35.tgz", - "integrity": "sha512-wc+VveszMLyMWFvXLkloixT4n0harUIVZjnpzztaZ0nKLuul7Z32iMt2fUFGAaZ4y1XWjFRMtCI5ewvyh4aIeg==", + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", + "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", "dev": true, "requires": { - "@types/events": "*", - "@types/minimatch": "*", - "@types/node": "*" + "@babel/helper-plugin-utils": "^7.0.0" } }, - "@types/handlebars": { - "version": "4.0.36", - "resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.0.36.tgz", - "integrity": "sha512-LjNiTX7TY7wtuC6y3QwC93hKMuqYhgV9A1uXBKNvZtVC8ZvyWAjZkJ5BvT0K7RKqORRYRLMrqCxpw5RgS+MdrQ==", - "dev": true - }, - "@types/highlight.js": { - "version": "9.12.2", - "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.2.tgz", - "integrity": "sha512-y5x0XD/WXDaGSyiTaTcKS4FurULJtSiYbGTeQd0m2LYZGBcZZ/7fM6t5H/DzeUF+kv8y6UfmF6yJABQsHcp9VQ==", - "dev": true - }, - "@types/jest": { - "version": "23.3.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-23.3.1.tgz", - "integrity": "sha512-/UMY+2GkOZ27Vrc51pqC5J8SPd39FKt7kkoGAtWJ8s4msj0b15KehDWIiJpWY3/7tLxBQLLzJhIBhnEsXdzpgw==", - "dev": true - }, - "@types/lodash": { - "version": "4.14.104", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.104.tgz", - "integrity": "sha512-ufQcVg4daO8xQ5kopxRHanqFdL4AI7ondQkV+2f+7mz3gvp0LkBx2zBRC6hfs3T87mzQFmf5Fck7Fi145Ul6NQ==", - "dev": true - }, - "@types/marked": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@types/marked/-/marked-0.3.0.tgz", - "integrity": "sha1-WDwiPdMzhaHdoBqvd7DNBBHEtSQ=", - "dev": true - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/node": { - "version": "10.5.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.7.tgz", - "integrity": "sha512-VkKcfuitP+Nc/TaTFH0B8qNmn+6NbI6crLkQonbedViVz7O2w8QV/GERPlkJ4bg42VGHiEWa31CoTOPs1q6z1w==", - "dev": true - }, - "@types/promise-polyfill": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@types/promise-polyfill/-/promise-polyfill-6.0.0.tgz", - "integrity": "sha1-CS0Aey8FAlQHCrVSxG+7HHstiyg=", - "dev": true - }, - "@types/shelljs": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.7.8.tgz", - "integrity": "sha512-M2giRw93PxKS7YjU6GZjtdV9HASdB7TWqizBXe4Ju7AqbKlWvTr0gNO92XH56D/gMxqD/jNHLNfC5hA34yGqrQ==", + "@babel/template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", + "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", "dev": true, "requires": { - "@types/glob": "*", - "@types/node": "*" + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" } }, - "@types/signals": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/signals/-/signals-1.0.1.tgz", - "integrity": "sha1-A775pRp+B7BZhNn0SAOsmcHHzqs=", - "dev": true - }, - "@types/sprintf-js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@types/sprintf-js/-/sprintf-js-1.1.0.tgz", - "integrity": "sha1-aFCpg4K1F8Sk0EAcY/KwvnbO4JI=", - "dev": true - }, - "@types/three": { - "version": "0.92.15", - "resolved": "https://registry.npmjs.org/@types/three/-/three-0.92.15.tgz", - "integrity": "sha512-V2mO1qWq6V67u+i4ppEBvpJHCnvv2wiuMlnk3wzeyedMxIMy9y9B6MFYTe5YVgujuylhAKC3VLPFM1spkWTFbw==", + "@babel/traverse": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.4.tgz", + "integrity": "sha512-Gw6qqkw/e6AGzlyj9KnkabJX7VcubqPtkUQVAwkc0wUMldr3A/hezNB3Rc5eIvId95iSGkGIOe5hh1kMKf951A==", "dev": true, "requires": { - "@types/webvr-api": "*" + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.4", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.11" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } } }, - "@types/webvr-api": { - "version": "0.0.34", - "resolved": "https://registry.npmjs.org/@types/webvr-api/-/webvr-api-0.0.34.tgz", - "integrity": "sha512-gVAPKK+L1blPJCFnUDmkIdRfIU8xbwl05MDXPRjnjoeDXUUzR6frPuyx9RQz+OCodmxlBcJOkjVTMTZi1BcuZw==", - "dev": true - }, - "abab": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", - "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", - "dev": true - }, - "acorn": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", - "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", - "dev": true - }, - "acorn-dynamic-import": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", - "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==", + "@babel/types": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", "dev": true, "requires": { - "acorn": "^5.0.0" + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } } }, - "acorn-globals": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.1.0.tgz", - "integrity": "sha512-KjZwU26uG3u6eZcfGbTULzFcsoz6pegNKtHPksZPOUsiKo5bUmiBPa38FuHZ/Eun+XYh/JCCkS9AS3Lu4McQOQ==", + "@cnakazawa/watch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", + "integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==", "dev": true, "requires": { - "acorn": "^5.0.0" + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } } }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "@jest/console": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.7.1.tgz", + "integrity": "sha512-iNhtIy2M8bXlAOULWVTUxmnelTLFneTNEkHCgPmgd+zNwy9zVddJ6oS5rZ9iwoscNdT5mMwUd0C51v/fSlzItg==", "dev": true, "requires": { - "acorn": "^3.0.4" + "@jest/source-map": "^24.3.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" }, "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "@jest/core": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.8.0.tgz", + "integrity": "sha512-R9rhAJwCBQzaRnrRgAdVfnglUuATXdwTRsYqs6NMdVcAl5euG8LtWDe+fVkN27YfKVBW61IojVsXKaOmSnqd/A==", "dev": true, "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "ajv-keywords": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "@jest/console": "^24.7.1", + "@jest/reporters": "^24.8.0", + "@jest/test-result": "^24.8.0", + "@jest/transform": "^24.8.0", + "@jest/types": "^24.8.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-changed-files": "^24.8.0", + "jest-config": "^24.8.0", + "jest-haste-map": "^24.8.0", + "jest-message-util": "^24.8.0", + "jest-regex-util": "^24.3.0", + "jest-resolve-dependencies": "^24.8.0", + "jest-runner": "^24.8.0", + "jest-runtime": "^24.8.0", + "jest-snapshot": "^24.8.0", + "jest-util": "^24.8.0", + "jest-validate": "^24.8.0", + "jest-watcher": "^24.8.0", + "micromatch": "^3.1.10", + "p-each-series": "^1.0.0", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "rimraf": "^2.5.4", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@jest/environment": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.8.0.tgz", + "integrity": "sha512-vlGt2HLg7qM+vtBrSkjDxk9K0YtRBi7HfRFaDxoRtyi+DyVChzhF20duvpdAnKVBV6W5tym8jm0U9EfXbDk1tw==", + "dev": true, + "requires": { + "@jest/fake-timers": "^24.8.0", + "@jest/transform": "^24.8.0", + "@jest/types": "^24.8.0", + "jest-mock": "^24.8.0" + } + }, + "@jest/fake-timers": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.8.0.tgz", + "integrity": "sha512-2M4d5MufVXwi6VzZhJ9f5S/wU4ud2ck0kxPof1Iz3zWx6Y+V2eJrES9jEktB6O3o/oEyk+il/uNu9PvASjWXQw==", + "dev": true, + "requires": { + "@jest/types": "^24.8.0", + "jest-message-util": "^24.8.0", + "jest-mock": "^24.8.0" + } + }, + "@jest/reporters": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.8.0.tgz", + "integrity": "sha512-eZ9TyUYpyIIXfYCrw0UHUWUvE35vx5I92HGMgS93Pv7du+GHIzl+/vh8Qj9MCWFK/4TqyttVBPakWMOfZRIfxw==", + "dev": true, + "requires": { + "@jest/environment": "^24.8.0", + "@jest/test-result": "^24.8.0", + "@jest/transform": "^24.8.0", + "@jest/types": "^24.8.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.2", + "istanbul-lib-coverage": "^2.0.2", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.1", + "istanbul-reports": "^2.1.1", + "jest-haste-map": "^24.8.0", + "jest-resolve": "^24.8.0", + "jest-runtime": "^24.8.0", + "jest-util": "^24.8.0", + "jest-worker": "^24.6.0", + "node-notifier": "^5.2.1", + "slash": "^2.0.0", + "source-map": "^0.6.0", + "string-length": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@jest/source-map": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.3.0.tgz", + "integrity": "sha512-zALZt1t2ou8le/crCeeiRYzvdnTzaIlpOWaet45lNSqNJUnXbppUUFR4ZUAlzgDmKee4Q5P/tKXypI1RiHwgag==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@jest/test-result": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.8.0.tgz", + "integrity": "sha512-+YdLlxwizlfqkFDh7Mc7ONPQAhA4YylU1s529vVM1rsf67vGZH/2GGm5uO8QzPeVyaVMobCQ7FTxl38QrKRlng==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/types": "^24.8.0", + "@types/istanbul-lib-coverage": "^2.0.0" + } + }, + "@jest/test-sequencer": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.8.0.tgz", + "integrity": "sha512-OzL/2yHyPdCHXEzhoBuq37CE99nkme15eHkAzXRVqthreWZamEMA0WoetwstsQBCXABhczpK03JNbc4L01vvLg==", + "dev": true, + "requires": { + "@jest/test-result": "^24.8.0", + "jest-haste-map": "^24.8.0", + "jest-runner": "^24.8.0", + "jest-runtime": "^24.8.0" + } + }, + "@jest/transform": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.8.0.tgz", + "integrity": "sha512-xBMfFUP7TortCs0O+Xtez2W7Zu1PLH9bvJgtraN1CDST6LBM/eTOZ9SfwS/lvV8yOfcDpFmwf9bq5cYbXvqsvA==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.8.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.8.0", + "jest-regex-util": "^24.3.0", + "jest-util": "^24.8.0", + "micromatch": "^3.1.10", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@jest/types": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.8.0.tgz", + "integrity": "sha512-g17UxVr2YfBtaMUxn9u/4+siG1ptg9IGYAYwvpwn61nBg779RXnjE/m7CxYcIzEt0AbHZZAHSEZNhkE2WxURVg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^12.0.9" + } + }, + "@types/babel__core": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.1.tgz", + "integrity": "sha512-+hjBtgcFPYyCTo0A15+nxrCVJL7aC6Acg87TXd5OW3QhHswdrOLoles+ldL2Uk8q++7yIfl4tURtztccdeeyOw==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.0.2.tgz", + "integrity": "sha512-NHcOfab3Zw4q5sEE2COkpfXjoE7o+PmqD9DQW4koUT3roNxwziUdXGnRndMat/LJNUtePwn1TlP4do3uoe3KZQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", + "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.6.tgz", + "integrity": "sha512-XYVgHF2sQ0YblLRMLNPB3CkFMewzFmlDsH/TneZFHUXDlABQgh88uOxuez7ZcXxayLFrqLwtDH1t+FmlFwNZxw==", + "dev": true, + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/chroma-js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-1.3.5.tgz", + "integrity": "sha512-GyKKeo/SR3FTD1nAuFcxdQ+1JW2E3Fwckto849cfUGvUvlCEuCbPc9zkmVGLp2MYs0fSc5QqLzJVY6VbD3NYMw==", + "dev": true + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", + "dev": true + }, + "@types/fs-extra": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.1.0.tgz", + "integrity": "sha512-AInn5+UBFIK9FK5xc9yP5e3TQSPNNgjHByqYcj9g5elVBnDQcQL7PlO1CIRy2gWlbwK7UPYqi7vRvFA44dCmYQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/handlebars": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.1.0.tgz", + "integrity": "sha512-gq9YweFKNNB1uFK71eRqsd4niVkXrxHugqWFQkeLRJvGjnxsLr16bYtcsG4tOFwmYi0Bax+wCkbf1reUfdl4kA==", + "dev": true, + "requires": { + "handlebars": "*" + } + }, + "@types/highlight.js": { + "version": "9.12.3", + "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.3.tgz", + "integrity": "sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ==", + "dev": true + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", + "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz", + "integrity": "sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", + "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "23.3.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-23.3.1.tgz", + "integrity": "sha512-/UMY+2GkOZ27Vrc51pqC5J8SPd39FKt7kkoGAtWJ8s4msj0b15KehDWIiJpWY3/7tLxBQLLzJhIBhnEsXdzpgw==", + "dev": true + }, + "@types/lodash": { + "version": "4.14.123", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.123.tgz", + "integrity": "sha512-pQvPkc4Nltyx7G1Ww45OjVqUsJP4UsZm+GWJpigXgkikZqJgRm4c48g027o6tdgubWHwFRF15iFd+Y4Pmqv6+Q==", + "dev": true + }, + "@types/marked": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-0.4.2.tgz", + "integrity": "sha512-cDB930/7MbzaGF6U3IwSQp6XBru8xWajF5PV2YZZeV8DyiliTuld11afVztGI9+yJZ29il5E+NpGA6ooV/Cjkg==", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/node": { + "version": "10.5.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.7.tgz", + "integrity": "sha512-VkKcfuitP+Nc/TaTFH0B8qNmn+6NbI6crLkQonbedViVz7O2w8QV/GERPlkJ4bg42VGHiEWa31CoTOPs1q6z1w==", + "dev": true + }, + "@types/promise-polyfill": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/promise-polyfill/-/promise-polyfill-6.0.0.tgz", + "integrity": "sha1-CS0Aey8FAlQHCrVSxG+7HHstiyg=", + "dev": true + }, + "@types/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-bZgjwIWu9gHCjirKJoOlLzGi5N0QgZ5t7EXEuoqyWCHTuSddURXo3FOBYDyRPNOWzZ6NbkLvZnVkn483Y/tvcQ==", + "dev": true, + "requires": { + "@types/glob": "*", + "@types/node": "*" + } + }, + "@types/signals": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/signals/-/signals-1.0.1.tgz", + "integrity": "sha1-A775pRp+B7BZhNn0SAOsmcHHzqs=", "dev": true }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "@types/sprintf-js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/sprintf-js/-/sprintf-js-1.1.0.tgz", + "integrity": "sha1-aFCpg4K1F8Sk0EAcY/KwvnbO4JI=", + "dev": true + }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", + "dev": true + }, + "@types/three": { + "version": "0.92.15", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.92.15.tgz", + "integrity": "sha512-V2mO1qWq6V67u+i4ppEBvpJHCnvv2wiuMlnk3wzeyedMxIMy9y9B6MFYTe5YVgujuylhAKC3VLPFM1spkWTFbw==", "dev": true, "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" + "@types/webvr-api": "*" } }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "@types/webvr-api": { + "version": "0.0.34", + "resolved": "https://registry.npmjs.org/@types/webvr-api/-/webvr-api-0.0.34.tgz", + "integrity": "sha512-gVAPKK+L1blPJCFnUDmkIdRfIU8xbwl05MDXPRjnjoeDXUUzR6frPuyx9RQz+OCodmxlBcJOkjVTMTZi1BcuZw==", + "dev": true + }, + "@types/yargs": { + "version": "12.0.12", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-12.0.12.tgz", + "integrity": "sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw==", + "dev": true + }, + "abab": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", + "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", + "dev": true + }, + "acorn": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", + "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", + "dev": true + }, + "acorn-dynamic-import": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", + "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==", + "dev": true, + "requires": { + "acorn": "^5.0.0" + } + }, + "acorn-globals": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.2.tgz", + "integrity": "sha512-BbzvZhVtZP+Bs1J1HcwrQe8ycfO0wStkSGxuul3He3GkHOIZ6eTqOkPuw9IP1X3+IkOo4wiJmwkobzXYz4wewQ==", + "dev": true, + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", + "dev": true + } + } + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "acorn-walk": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "dev": true + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", "dev": true }, "ansi-escapes": { @@ -288,15 +1512,6 @@ "normalize-path": "^2.0.0" } }, - "append-transform": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", - "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", - "dev": true, - "requires": { - "default-require-extensions": "^2.0.0" - } - }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -429,15 +1644,6 @@ "integrity": "sha1-bIw/uCfdQ+45GPJ7gngqt2WKb9k=", "dev": true }, - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "^4.17.10" - } - }, "async-each": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", @@ -527,9 +1733,9 @@ } }, "babel-generator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz", - "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", "dev": true, "requires": { "babel-messages": "^6.23.0", @@ -538,7 +1744,7 @@ "detect-indent": "^4.0.0", "jsesc": "^1.3.0", "lodash": "^4.17.4", - "source-map": "^0.5.6", + "source-map": "^0.5.7", "trim-right": "^1.0.1" }, "dependencies": { @@ -653,13 +1859,55 @@ } }, "babel-jest": { - "version": "23.4.2", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-23.4.2.tgz", - "integrity": "sha512-wg1LJ2tzsafXqPFVgAsYsMCVD5U7kwJZAvbZIxVm27iOewsQw1BR7VZifDlMTEWVo3wasoPPyMdKXWCsfFPr3Q==", - "dev": true, - "requires": { - "babel-plugin-istanbul": "^4.1.6", - "babel-preset-jest": "^23.2.0" + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.8.0.tgz", + "integrity": "sha512-+5/kaZt4I9efoXzPlZASyK/lN9qdRKmmUav9smVc0ruPQD7IsfucQ87gpOE8mn2jbDuS6M/YOW6n3v9ZoIfgnw==", + "dev": true, + "requires": { + "@jest/transform": "^24.8.0", + "@jest/types": "^24.8.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.6.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "babel-messages": { @@ -696,28 +1944,69 @@ } }, "babel-plugin-istanbul": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz", - "integrity": "sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.4.tgz", + "integrity": "sha512-dySz4VJMH+dpndj0wjJ8JPs/7i1TdSPb1nRrn56/92pKOF9VKC1FMFJmMXjzlGGusnCAqujP6PBCiKq0sVA+YQ==", "dev": true, "requires": { - "babel-plugin-syntax-object-rest-spread": "^6.13.0", - "find-up": "^2.1.0", - "istanbul-lib-instrument": "^1.10.1", - "test-exclude": "^4.2.1" + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.3.0", + "test-exclude": "^5.2.3" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + } } }, "babel-plugin-jest-hoist": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz", - "integrity": "sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=", - "dev": true - }, - "babel-plugin-syntax-object-rest-spread": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", - "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", - "dev": true + "version": "24.6.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.6.0.tgz", + "integrity": "sha512-3pKNH6hMt9SbOv0F3WVmy5CWQ4uogS3k0GY5XLyQHJ9EGpAT9XWkFd2ZiXXtkwFHdAHa5j7w7kfxSP5lAIwu7w==", + "dev": true, + "requires": { + "@types/babel__traverse": "^7.0.6" + } }, "babel-plugin-transform-es2015-arrow-functions": { "version": "6.22.0", @@ -1005,13 +2294,13 @@ } }, "babel-preset-jest": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz", - "integrity": "sha1-jsegOhOPABoaj7HoETZSvxpV2kY=", + "version": "24.6.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.6.0.tgz", + "integrity": "sha512-pdZqLEdmy1ZK5kyRUfvBb2IfTPb2BUvIJczlPspS8fWmBQslNNDBqVfh7BW5leOVJMDZKzjD8XEyABTk6gQ5yw==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^23.2.0", - "babel-plugin-syntax-object-rest-spread": "^6.13.0" + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.6.0" } }, "babel-register": { @@ -1185,7 +2474,6 @@ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, - "optional": true, "requires": { "tweetnacl": "^0.14.3" } @@ -1218,9 +2506,9 @@ } }, "browser-process-hrtime": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz", - "integrity": "sha1-Ql1opY00R/AqBKqJQYf86K+Le44=", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", "dev": true }, "browser-resolve": { @@ -1370,18 +2658,18 @@ "dev": true }, "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, "capture-exit": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-1.2.0.tgz", - "integrity": "sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", "dev": true, "requires": { - "rsvp": "^3.3.3" + "rsvp": "^4.8.4" } }, "caseless": { @@ -1390,17 +2678,6 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "optional": true, - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, "chai": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", @@ -1464,9 +2741,9 @@ "dev": true }, "ci-info": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.3.tgz", - "integrity": "sha512-SK/846h/Rcy8q9Z9CAwGBLfCJ6EkjJWdpelWDufQpqVDYq2Wnnv8zlSO6AMQap02jvhVruKKpEtQOufo3pFhLg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, "circular-json": { @@ -1591,9 +2868,9 @@ "dev": true }, "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", "dev": true, "requires": { "delayed-stream": "~1.0.0" @@ -1605,12 +2882,6 @@ "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, - "compare-versions": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.3.0.tgz", - "integrity": "sha512-MAAAIOdi2s4Gl6rZ76PNcUa9IOYB+5ICdT41o5uMRf09aEu/F9RK+qhe8RjXNPwcTjGV7KU7h2P/fljThFVqyQ==", - "dev": true - }, "component-emitter": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", @@ -1642,10 +2913,13 @@ "dev": true }, "convert-source-map": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", - "dev": true + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } }, "copy-descriptor": { "version": "0.1.1", @@ -1696,15 +2970,15 @@ } }, "cssom": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.4.tgz", - "integrity": "sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", + "integrity": "sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A==", "dev": true }, "cssstyle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.0.0.tgz", - "integrity": "sha512-Bpuh47j2mRMY60X90mXaJAEtJwxvA2roZzbgwAXYhMbmwmakdRr4Cq9L5SkleKJNLOKqHIa2YWyOXDX3VgggSQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.2.tgz", + "integrity": "sha512-43wY3kl1CVQSvL7wUY1qXkxVGkStjpkDmVjiIKX8R97uhajy8Bybay78uOtqvh7Q5GK75dNPfW0geWjE6qQQow==", "dev": true, "requires": { "cssom": "0.3.x" @@ -1720,21 +2994,26 @@ } }, "data-urls": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.0.0.tgz", - "integrity": "sha512-ai40PPQR0Fn1lD2PPie79CibnlMN2AYiDhwFX/rZHVsxbs5kNJSjegqXIprhouGXlRdEnfybva7kqRGnB6mypA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", "dev": true, "requires": { - "abab": "^1.0.4", - "whatwg-mimetype": "^2.0.0", - "whatwg-url": "^6.4.0" + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" }, "dependencies": { - "abab": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", - "integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=", - "dev": true + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } } } }, @@ -1780,15 +3059,6 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "default-require-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", - "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", - "dev": true, - "requires": { - "strip-bom": "^3.0.0" - } - }, "define-properties": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", @@ -1908,6 +3178,12 @@ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, + "diff-sequences": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.3.0.tgz", + "integrity": "sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw==", + "dev": true + }, "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -1937,12 +3213,26 @@ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "dev": true, - "optional": true, "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, "error-ex": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", @@ -1983,9 +3273,9 @@ "dev": true }, "escodegen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz", - "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", + "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", "dev": true, "requires": { "esprima": "^3.1.3", @@ -2011,89 +3301,103 @@ } }, "eslint": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.3.0.tgz", - "integrity": "sha512-N/tCqlMKkyNvAvLu+zI9AqDasnSLt00K+Hu8kdsERliC9jYEc8ck12XtjvOXrBKu8fK6RrBcN9bat6Xk++9jAg==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", "dev": true, "requires": { - "ajv": "^6.5.0", - "babel-code-frame": "^6.26.0", + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", "chalk": "^2.1.0", "cross-spawn": "^6.0.5", - "debug": "^3.1.0", - "doctrine": "^2.1.0", - "eslint-scope": "^4.0.0", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", "eslint-utils": "^1.3.1", "eslint-visitor-keys": "^1.0.0", - "espree": "^4.0.0", + "espree": "^5.0.1", "esquery": "^1.0.1", "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", + "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", "glob": "^7.1.2", "globals": "^11.7.0", - "ignore": "^4.0.2", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^5.2.0", - "is-resolvable": "^1.1.0", - "js-yaml": "^3.11.0", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.3.0", - "lodash": "^4.17.5", + "lodash": "^4.17.11", "minimatch": "^3.0.4", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", "optionator": "^0.8.2", "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", "progress": "^2.0.0", - "regexpp": "^2.0.0", - "require-uncached": "^1.0.3", - "semver": "^5.5.0", - "string.prototype.matchall": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", "strip-ansi": "^4.0.0", "strip-json-comments": "^2.0.1", - "table": "^4.0.3", + "table": "^5.2.3", "text-table": "^0.2.0" }, "dependencies": { - "acorn": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", - "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==", - "dev": true + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } }, - "acorn-jsx": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz", - "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==", + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", "dev": true, "requires": { - "acorn": "^5.0.3" + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" } }, + "acorn": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", + "dev": true + }, + "acorn-jsx": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", + "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", + "dev": true + }, "ajv": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.2.tgz", - "integrity": "sha512-hOs7GfvI6tUI1LfZddH82ky6mOMyTuY0mk7kE2pWpmhhUSkumzaTO5vbVwij39MdwPQWCV4Zv57Eo06NtL/GVA==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.1" + "uri-js": "^4.2.2" } }, - "ajv-keywords": { + "ansi-escapes": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", - "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", "dev": true }, "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "ansi-styles": { @@ -2106,9 +3410,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -2116,6 +3420,12 @@ "supports-color": "^5.3.0" } }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -2130,18 +3440,27 @@ } }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "requires": { - "ms": "2.0.0" + "esutils": "^2.0.2" } }, "eslint-scope": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", - "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", "dev": true, "requires": { "esrecurse": "^4.1.0", @@ -2149,13 +3468,25 @@ } }, "espree": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz", - "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "external-editor": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", + "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", "dev": true, "requires": { - "acorn": "^5.6.0", - "acorn-jsx": "^4.1.1" + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" } }, "fast-deep-equal": { @@ -2164,37 +3495,93 @@ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, "globals": { - "version": "11.7.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", - "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==", + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, "ignore": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.3.tgz", - "integrity": "sha512-Z/vAH2GGIEATQnBVXMclE2IGV6i0GyVngKThcGZ5kHgHMxLo9Ow2+XHRq1aEKEej5vOF1TPJNbvX6J/anT0M7A==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, "inquirer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", - "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz", + "integrity": "sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-width": "^2.0.0", - "external-editor": "^2.1.0", + "external-editor": "^3.0.3", "figures": "^2.0.0", - "lodash": "^4.3.0", + "lodash": "^4.17.11", "mute-stream": "0.0.7", "run-async": "^2.2.0", - "rxjs": "^5.5.2", + "rxjs": "^6.4.0", "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", + "strip-ansi": "^5.1.0", "through": "^2.3.6" + }, + "dependencies": { + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, "json-schema-traverse": { @@ -2203,6 +3590,54 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -2210,29 +3645,66 @@ "dev": true, "requires": { "ansi-regex": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + } } }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" } }, "table": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", - "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz", + "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==", "dev": true, "requires": { - "ajv": "^6.0.1", - "ajv-keywords": "^3.0.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" + "ajv": "^6.9.1", + "lodash": "^4.17.11", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" } } } @@ -2450,27 +3922,39 @@ "dev": true }, "exec-sh": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.2.tgz", - "integrity": "sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==", - "dev": true, - "requires": { - "merge": "^1.2.0" - } + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.2.tgz", + "integrity": "sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg==", + "dev": true }, "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + } } }, "exit": { @@ -2498,17 +3982,17 @@ } }, "expect": { - "version": "23.4.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-23.4.0.tgz", - "integrity": "sha1-baTsyZwUcSU+cogziYOtHrrbYMM=", + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.8.0.tgz", + "integrity": "sha512-/zYvP8iMDrzaaxHVa724eJBCKqSHmO0FA7EDkBiRHxg6OipmMn1fN+C8T9L9K8yr7UONkOifu6+LLH+z76CnaA==", "dev": true, "requires": { + "@jest/types": "^24.8.0", "ansi-styles": "^3.2.0", - "jest-diff": "^23.2.0", - "jest-get-type": "^22.1.0", - "jest-matcher-utils": "^23.2.0", - "jest-message-util": "^23.4.0", - "jest-regex-util": "^23.3.0" + "jest-get-type": "^24.8.0", + "jest-matcher-utils": "^24.8.0", + "jest-message-util": "^24.8.0", + "jest-regex-util": "^24.3.0" }, "dependencies": { "ansi-styles": { @@ -2627,16 +4111,6 @@ "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", "dev": true }, - "fileset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", - "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", - "dev": true, - "requires": { - "glob": "^7.0.3", - "minimatch": "^3.0.3" - } - }, "fill-range": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", @@ -2710,6 +4184,12 @@ "write": "^0.2.1" } }, + "flatted": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "dev": true + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -2738,13 +4218,13 @@ "dev": true }, "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "dev": true, "requires": { "asynckit": "^0.4.0", - "combined-stream": "1.0.6", + "combined-stream": "^1.0.6", "mime-types": "^2.1.12" } }, @@ -2775,14 +4255,14 @@ "dev": true }, "fsevents": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", "dev": true, "optional": true, "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" }, "dependencies": { "abbrev": { @@ -2794,7 +4274,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -2803,7 +4284,7 @@ "optional": true }, "are-we-there-yet": { - "version": "1.1.4", + "version": "1.1.5", "bundled": true, "dev": true, "optional": true, @@ -2815,19 +4296,21 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "chownr": { - "version": "1.0.1", + "version": "1.1.1", "bundled": true, "dev": true, "optional": true @@ -2835,17 +4318,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -2854,16 +4340,16 @@ "optional": true }, "debug": { - "version": "2.6.9", + "version": "4.1.1", "bundled": true, "dev": true, "optional": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "deep-extend": { - "version": "0.5.1", + "version": "0.6.0", "bundled": true, "dev": true, "optional": true @@ -2912,7 +4398,7 @@ } }, "glob": { - "version": "7.1.2", + "version": "7.1.3", "bundled": true, "dev": true, "optional": true, @@ -2932,12 +4418,12 @@ "optional": true }, "iconv-lite": { - "version": "0.4.21", + "version": "0.4.24", "bundled": true, "dev": true, "optional": true, "requires": { - "safer-buffer": "^2.1.0" + "safer-buffer": ">= 2.1.2 < 3" } }, "ignore-walk": { @@ -2962,7 +4448,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -2974,6 +4461,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2988,6 +4476,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2995,19 +4484,21 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { - "version": "2.2.4", + "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { - "safe-buffer": "^5.1.1", + "safe-buffer": "^5.1.2", "yallist": "^3.0.0" } }, "minizlib": { - "version": "1.1.0", + "version": "1.2.1", "bundled": true, "dev": true, "optional": true, @@ -3019,40 +4510,48 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } }, "ms": { - "version": "2.0.0", + "version": "2.1.1", "bundled": true, "dev": true, "optional": true }, + "nan": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", + "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", + "dev": true, + "optional": true + }, "needle": { - "version": "2.2.0", + "version": "2.3.0", "bundled": true, "dev": true, "optional": true, "requires": { - "debug": "^2.1.2", + "debug": "^4.1.0", "iconv-lite": "^0.4.4", "sax": "^1.2.4" } }, "node-pre-gyp": { - "version": "0.10.0", + "version": "0.12.0", "bundled": true, "dev": true, "optional": true, "requires": { "detect-libc": "^1.0.2", "mkdirp": "^0.5.1", - "needle": "^2.2.0", + "needle": "^2.2.1", "nopt": "^4.0.1", "npm-packlist": "^1.1.6", "npmlog": "^4.0.2", - "rc": "^1.1.7", + "rc": "^1.2.7", "rimraf": "^2.6.1", "semver": "^5.3.0", "tar": "^4" @@ -3069,13 +4568,13 @@ } }, "npm-bundled": { - "version": "1.0.3", + "version": "1.0.6", "bundled": true, "dev": true, "optional": true }, "npm-packlist": { - "version": "1.1.10", + "version": "1.4.1", "bundled": true, "dev": true, "optional": true, @@ -3099,7 +4598,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -3111,6 +4611,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -3150,12 +4651,12 @@ "optional": true }, "rc": { - "version": "1.2.7", + "version": "1.2.8", "bundled": true, "dev": true, "optional": true, "requires": { - "deep-extend": "^0.5.1", + "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" @@ -3185,18 +4686,19 @@ } }, "rimraf": { - "version": "2.6.2", + "version": "2.6.3", "bundled": true, "dev": true, "optional": true, "requires": { - "glob": "^7.0.5" + "glob": "^7.1.3" } }, "safe-buffer": { - "version": "5.1.1", + "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -3211,7 +4713,7 @@ "optional": true }, "semver": { - "version": "5.5.0", + "version": "5.7.0", "bundled": true, "dev": true, "optional": true @@ -3232,6 +4734,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3251,6 +4754,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3262,17 +4766,17 @@ "optional": true }, "tar": { - "version": "4.4.1", + "version": "4.4.8", "bundled": true, "dev": true, "optional": true, "requires": { - "chownr": "^1.0.1", + "chownr": "^1.1.1", "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", + "safe-buffer": "^5.1.2", "yallist": "^3.0.2" } }, @@ -3283,23 +4787,25 @@ "optional": true }, "wide-align": { - "version": "1.1.2", + "version": "1.1.3", "bundled": true, "dev": true, "optional": true, "requires": { - "string-width": "^1.0.2" + "string-width": "^1.0.2 || 2" } }, "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { - "version": "3.0.2", + "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -3334,10 +4840,13 @@ "dev": true }, "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } }, "get-value": { "version": "2.0.6", @@ -3435,91 +4944,22 @@ "dev": true }, "handlebars": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", - "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", + "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", "dev": true, "requires": { - "async": "^1.4.0", + "neo-async": "^2.6.0", "optimist": "^0.6.1", - "source-map": "^0.4.4", - "uglify-js": "^2.6" + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" }, "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true, - "optional": true - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "optional": true, - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - } - }, "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, - "optional": true, - "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "optional": true - } - } - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true, - "optional": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "optional": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - } + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true } } }, @@ -3530,13 +4970,39 @@ "dev": true }, "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "dev": true, "requires": { - "ajv": "^5.1.0", + "ajv": "^6.5.5", "har-schema": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + } } }, "has": { @@ -3563,12 +5029,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true - }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -3636,9 +5096,9 @@ "dev": true }, "highlight.js": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", - "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=", + "version": "9.15.6", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.6.tgz", + "integrity": "sha512-zozTAWM1D6sozHo8kqhfYgsac+B+q0PmsjXeyDrYIHHcBN0zTVT66+s2GW1GZv7DbyaROdLXKdabwS/WqPyIdQ==", "dev": true }, "home-or-tmp": { @@ -3689,23 +5149,84 @@ "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", "dev": true }, + "import-fresh": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz", + "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } + } + }, "import-local": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", - "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", "dev": true, "requires": { - "pkg-dir": "^2.0.0", + "pkg-dir": "^3.0.0", "resolve-cwd": "^2.0.0" }, "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", "dev": true, "requires": { - "find-up": "^2.1.0" + "find-up": "^3.0.0" } } } @@ -3801,9 +5322,9 @@ } }, "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", "dev": true }, "invariant": { @@ -3816,9 +5337,9 @@ } }, "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, "is-accessor-descriptor": { @@ -3867,12 +5388,12 @@ "dev": true }, "is-ci": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz", - "integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", "dev": true, "requires": { - "ci-info": "^1.0.0" + "ci-info": "^2.0.0" } }, "is-data-descriptor": { @@ -3952,9 +5473,9 @@ "dev": true }, "is-generator-fn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-1.0.0.tgz", - "integrity": "sha1-lp1J4bszKfa7fwkIm+JleLLd1Go=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true }, "is-glob": { @@ -3966,280 +5487,1200 @@ "is-extglob": "^1.0.0" } }, - "is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", - "dev": true - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", + "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.4.tgz", + "integrity": "sha512-QCHGyZEK0bfi9GR215QSm+NJwFKEShbtc7tfbUdLAEzn3kKhLDDZqvljn8rPZM9v8CEOhzL1nlYoO4r1ryl67w==", "dev": true, "requires": { - "kind-of": "^3.0.2" + "handlebars": "^4.1.2" } }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "jest": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-24.8.0.tgz", + "integrity": "sha512-o0HM90RKFRNWmAWvlyV8i5jGZ97pFwkeVoGvPW1EtLTgJc2+jcuqcbbqcSZLE/3f2S5pt0y2ZBETuhpWNl1Reg==", "dev": true, "requires": { - "is-path-inside": "^1.0.0" + "import-local": "^2.0.0", + "jest-cli": "^24.8.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "jest-cli": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.8.0.tgz", + "integrity": "sha512-+p6J00jSMPQ116ZLlHJJvdf8wbjNbZdeSX9ptfHX06/MSNaXmKihQzx5vQcw0q2G6JsdVkUIdWbOWtSnaYs3yA==", + "dev": true, + "requires": { + "@jest/core": "^24.8.0", + "@jest/test-result": "^24.8.0", + "@jest/types": "^24.8.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "import-local": "^2.0.0", + "is-ci": "^2.0.0", + "jest-config": "^24.8.0", + "jest-util": "^24.8.0", + "jest-validate": "^24.8.0", + "prompts": "^2.0.1", + "realpath-native": "^1.1.0", + "yargs": "^12.0.2" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "jest-changed-files": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.8.0.tgz", + "integrity": "sha512-qgANC1Yrivsq+UrLXsvJefBKVoCsKB0Hv+mBb6NMjjZ90wwxCDmU3hsCXBya30cH+LnPYjwgcU65i6yJ5Nfuug==", "dev": true, "requires": { - "path-is-inside": "^1.0.1" + "@jest/types": "^24.8.0", + "execa": "^1.0.0", + "throat": "^4.0.0" } }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "jest-config": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.8.0.tgz", + "integrity": "sha512-Czl3Nn2uEzVGsOeaewGWoDPD8GStxCpAe0zOYs2x2l0fZAgPbCr3uwUkgNKV3LwE13VXythM946cd5rdGkkBZw==", "dev": true, "requires": { - "isobject": "^3.0.1" + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.8.0", + "@jest/types": "^24.8.0", + "babel-jest": "^24.8.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.8.0", + "jest-environment-node": "^24.8.0", + "jest-get-type": "^24.8.0", + "jest-jasmine2": "^24.8.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.8.0", + "jest-util": "^24.8.0", + "jest-validate": "^24.8.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.8.0", + "realpath-native": "^1.1.0" }, "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, - "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "jest-diff": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.8.0.tgz", + "integrity": "sha512-wxetCEl49zUpJ/bvUmIFjd/o52J+yWcoc5ZyPq4/W1LUKGEhRYDIbP1KcF6t+PvqNrGAFk4/JhtxDq/Nnzs66g==", "dev": true, "requires": { - "has": "^1.0.1" + "chalk": "^2.0.1", + "diff-sequences": "^24.3.0", + "jest-get-type": "^24.8.0", + "pretty-format": "^24.8.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-symbol": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", - "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "jest-docblock": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.3.0.tgz", + "integrity": "sha512-nlANmF9Yq1dufhFlKG9rasfQlrY7wINJbo3q01tu56Jv5eBU5jirylhF2O5ZBnLxzOVBGRDz/9NAwNyBtG4Nyg==", "dev": true, "requires": { - "isarray": "1.0.0" - } - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "istanbul-api": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.1.tgz", - "integrity": "sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g==", - "dev": true, - "requires": { - "async": "^2.1.4", - "compare-versions": "^3.1.0", - "fileset": "^2.0.2", - "istanbul-lib-coverage": "^1.2.0", - "istanbul-lib-hook": "^1.2.0", - "istanbul-lib-instrument": "^1.10.1", - "istanbul-lib-report": "^1.1.4", - "istanbul-lib-source-maps": "^1.2.4", - "istanbul-reports": "^1.3.0", - "js-yaml": "^3.7.0", - "mkdirp": "^0.5.1", - "once": "^1.4.0" + "detect-newline": "^2.1.0" } }, - "istanbul-lib-coverage": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz", - "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", - "dev": true + "jest-each": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.8.0.tgz", + "integrity": "sha512-NrwK9gaL5+XgrgoCsd9svsoWdVkK4gnvyhcpzd6m487tXHqIdYeykgq3MKI1u4I+5Zf0tofr70at9dWJDeb+BA==", + "dev": true, + "requires": { + "@jest/types": "^24.8.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.8.0", + "jest-util": "^24.8.0", + "pretty-format": "^24.8.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } }, - "istanbul-lib-hook": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.1.tgz", - "integrity": "sha512-eLAMkPG9FU0v5L02lIkcj/2/Zlz9OuluaXikdr5iStk8FDbSwAixTK9TkYxbF0eNnzAJTwM2fkV2A1tpsIp4Jg==", + "jest-environment-jsdom": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.8.0.tgz", + "integrity": "sha512-qbvgLmR7PpwjoFjM/sbuqHJt/NCkviuq9vus9NBn/76hhSidO+Z6Bn9tU8friecegbJL8gzZQEMZBQlFWDCwAQ==", "dev": true, "requires": { - "append-transform": "^1.0.0" + "@jest/environment": "^24.8.0", + "@jest/fake-timers": "^24.8.0", + "@jest/types": "^24.8.0", + "jest-mock": "^24.8.0", + "jest-util": "^24.8.0", + "jsdom": "^11.5.1" } }, - "istanbul-lib-instrument": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz", - "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==", + "jest-environment-node": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.8.0.tgz", + "integrity": "sha512-vIGUEScd1cdDgR6sqn2M08sJTRLQp6Dk/eIkCeO4PFHxZMOgy+uYLPMC4ix3PEfM5Au/x3uQ/5Tl0DpXXZsJ/Q==", "dev": true, "requires": { - "babel-generator": "^6.18.0", - "babel-template": "^6.16.0", - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", - "babylon": "^6.18.0", - "istanbul-lib-coverage": "^1.2.0", - "semver": "^5.3.0" + "@jest/environment": "^24.8.0", + "@jest/fake-timers": "^24.8.0", + "@jest/types": "^24.8.0", + "jest-mock": "^24.8.0", + "jest-util": "^24.8.0" } }, - "istanbul-lib-report": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz", - "integrity": "sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA==", + "jest-get-type": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.8.0.tgz", + "integrity": "sha512-RR4fo8jEmMD9zSz2nLbs2j0zvPpk/KCEz3a62jJWbd2ayNo0cb+KFRxPHVhE4ZmgGJEQp0fosmNz84IfqM8cMQ==", + "dev": true + }, + "jest-haste-map": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.8.0.tgz", + "integrity": "sha512-ZBPRGHdPt1rHajWelXdqygIDpJx8u3xOoLyUBWRW28r3tagrgoepPrzAozW7kW9HrQfhvmiv1tncsxqHJO1onQ==", "dev": true, "requires": { - "istanbul-lib-coverage": "^1.2.0", - "mkdirp": "^0.5.1", - "path-parse": "^1.0.5", - "supports-color": "^3.1.2" + "@jest/types": "^24.8.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.4.0", + "jest-util": "^24.8.0", + "jest-worker": "^24.6.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3", + "walker": "^1.0.7" }, "dependencies": { - "has-flag": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { - "has-flag": "^1.0.0" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" } } } }, - "istanbul-lib-source-maps": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.5.tgz", - "integrity": "sha512-8O2T/3VhrQHn0XcJbP1/GN7kXMiRAlPi+fj3uEHrjBD8Oz7Py0prSC25C09NuAZS6bgW1NNKAvCSHZXB0irSGA==", + "jest-jasmine2": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.8.0.tgz", + "integrity": "sha512-cEky88npEE5LKd5jPpTdDCLvKkdyklnaRycBXL6GNmpxe41F0WN44+i7lpQKa/hcbXaQ+rc9RMaM4dsebrYong==", "dev": true, "requires": { - "debug": "^3.1.0", - "istanbul-lib-coverage": "^1.2.0", - "mkdirp": "^0.5.1", - "rimraf": "^2.6.1", - "source-map": "^0.5.3" + "@babel/traverse": "^7.1.0", + "@jest/environment": "^24.8.0", + "@jest/test-result": "^24.8.0", + "@jest/types": "^24.8.0", + "chalk": "^2.0.1", + "co": "^4.6.0", + "expect": "^24.8.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^24.8.0", + "jest-matcher-utils": "^24.8.0", + "jest-message-util": "^24.8.0", + "jest-runtime": "^24.8.0", + "jest-snapshot": "^24.8.0", + "jest-util": "^24.8.0", + "pretty-format": "^24.8.0", + "throat": "^4.0.0" }, "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "ms": "2.0.0" + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" } } } }, - "istanbul-reports": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.3.0.tgz", - "integrity": "sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA==", + "jest-leak-detector": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.8.0.tgz", + "integrity": "sha512-cG0yRSK8A831LN8lIHxI3AblB40uhv0z+SsQdW3GoMMVcK+sJwrIIyax5tu3eHHNJ8Fu6IMDpnLda2jhn2pD/g==", "dev": true, "requires": { - "handlebars": "^4.0.3" + "pretty-format": "^24.8.0" } }, - "jest": { - "version": "23.4.2", - "resolved": "https://registry.npmjs.org/jest/-/jest-23.4.2.tgz", - "integrity": "sha512-w10HGpVFWT1oN8B2coxeiMEsZoggkDaw3i26xHGLU+rsR+LYkBk8qpZCgi+1cD1S6ttPjZDL8E8M99lmNhgTeA==", + "jest-matcher-utils": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.8.0.tgz", + "integrity": "sha512-lex1yASY51FvUuHgm0GOVj7DCYEouWSlIYmCW7APSqB9v8mXmKSn5+sWVF0MhuASG0bnYY106/49JU1FZNl5hw==", "dev": true, "requires": { - "import-local": "^1.0.0", - "jest-cli": "^23.4.2" + "chalk": "^2.0.1", + "jest-diff": "^24.8.0", + "jest-get-type": "^24.8.0", + "pretty-format": "^24.8.0" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -4250,9 +6691,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -4260,63 +6701,10 @@ "supports-color": "^5.3.0" } }, - "jest-cli": { - "version": "23.4.2", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-23.4.2.tgz", - "integrity": "sha512-vaDzy0wRWrgSfz4ZImCqD2gtZqCSoEWp60y3USvGDxA2b4K0rGj2voru6a5scJFjDx5GCiNWKpz2E8IdWDVjdw==", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.1", - "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "import-local": "^1.0.0", - "is-ci": "^1.0.10", - "istanbul-api": "^1.3.1", - "istanbul-lib-coverage": "^1.2.0", - "istanbul-lib-instrument": "^1.10.1", - "istanbul-lib-source-maps": "^1.2.4", - "jest-changed-files": "^23.4.2", - "jest-config": "^23.4.2", - "jest-environment-jsdom": "^23.4.0", - "jest-get-type": "^22.1.0", - "jest-haste-map": "^23.4.1", - "jest-message-util": "^23.4.0", - "jest-regex-util": "^23.3.0", - "jest-resolve-dependencies": "^23.4.2", - "jest-runner": "^23.4.2", - "jest-runtime": "^23.4.2", - "jest-snapshot": "^23.4.2", - "jest-util": "^23.4.0", - "jest-validate": "^23.4.0", - "jest-watcher": "^23.4.0", - "jest-worker": "^23.2.0", - "micromatch": "^2.3.11", - "node-notifier": "^5.2.1", - "prompts": "^0.1.9", - "realpath-native": "^1.0.0", - "rimraf": "^2.5.4", - "slash": "^1.0.0", - "string-length": "^2.0.0", - "strip-ansi": "^4.0.0", - "which": "^1.2.12", - "yargs": "^11.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -4324,34 +6712,20 @@ } } }, - "jest-changed-files": { - "version": "23.4.2", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-23.4.2.tgz", - "integrity": "sha512-EyNhTAUWEfwnK0Is/09LxoqNDOn7mU7S3EHskG52djOFS/z+IT0jT3h3Ql61+dklcG7bJJitIWEMB4Sp1piHmA==", - "dev": true, - "requires": { - "throat": "^4.0.0" - } - }, - "jest-config": { - "version": "23.4.2", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-23.4.2.tgz", - "integrity": "sha512-CDJGO4H+7P+T6khaSHEjTxqVaIlmQMEFAyJFOVrAQeM+Xn12iZ+YY8Pluk1RDxi8Jqj9DoE09PHQzASCGePGtg==", + "jest-message-util": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.8.0.tgz", + "integrity": "sha512-p2k71rf/b6ns8btdB0uVdljWo9h0ovpnEe05ZKWceQGfXYr4KkzgKo3PBi8wdnd9OtNh46VpNIJynUn/3MKm1g==", "dev": true, "requires": { - "babel-core": "^6.0.0", - "babel-jest": "^23.4.2", + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.8.0", + "@jest/types": "^24.8.0", + "@types/stack-utils": "^1.0.1", "chalk": "^2.0.1", - "glob": "^7.1.1", - "jest-environment-jsdom": "^23.4.0", - "jest-environment-node": "^23.4.0", - "jest-get-type": "^22.1.0", - "jest-jasmine2": "^23.4.2", - "jest-regex-util": "^23.3.0", - "jest-resolve": "^23.4.1", - "jest-util": "^23.4.0", - "jest-validate": "^23.4.0", - "pretty-format": "^23.2.0" + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" }, "dependencies": { "ansi-styles": { @@ -4363,258 +6737,301 @@ "color-convert": "^1.9.0" } }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "jest-diff": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-23.2.0.tgz", - "integrity": "sha1-nyz0tR4Sx5FVAgCrwWtHEwrxBio=", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "diff": "^3.2.0", - "jest-get-type": "^22.1.0", - "pretty-format": "^23.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "color-convert": "^1.9.0" + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "kind-of": "^6.0.0" } }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "jest-docblock": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-23.2.0.tgz", - "integrity": "sha1-8IXh8YVI2Z/dabICB+b9VdkTg6c=", - "dev": true, - "requires": { - "detect-newline": "^2.1.0" - } - }, - "jest-each": { - "version": "23.4.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-23.4.0.tgz", - "integrity": "sha1-L6nt2J2qGk7cn/m/YGKja3E0UUM=", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "pretty-format": "^23.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "kind-of": "^6.0.0" } }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "jest-environment-jsdom": { - "version": "23.4.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz", - "integrity": "sha1-BWp5UrP+pROsYqFAosNox52eYCM=", - "dev": true, - "requires": { - "jest-mock": "^23.2.0", - "jest-util": "^23.4.0", - "jsdom": "^11.5.1" - } - }, - "jest-environment-node": { - "version": "23.4.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-23.4.0.tgz", - "integrity": "sha1-V+gO0IQd6jAxZ8zozXlSHeuv3hA=", - "dev": true, - "requires": { - "jest-mock": "^23.2.0", - "jest-util": "^23.4.0" - } - }, - "jest-get-type": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", - "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", - "dev": true - }, - "jest-haste-map": { - "version": "23.4.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-23.4.1.tgz", - "integrity": "sha512-PGQxOEGAfRbTyJkmZeOKkVSs+KVeWgG625p89KUuq+sIIchY5P8iPIIc+Hw2tJJPBzahU3qopw1kF/qyhDdNBw==", - "dev": true, - "requires": { - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.1.11", - "jest-docblock": "^23.2.0", - "jest-serializer": "^23.0.1", - "jest-worker": "^23.2.0", - "micromatch": "^2.3.11", - "sane": "^2.0.0" - } - }, - "jest-jasmine2": { - "version": "23.4.2", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-23.4.2.tgz", - "integrity": "sha512-MUoqn41XHMQe5u8QvRTH2HahpBNzImnnjS3pV/T7LvrCM6f2zfGdi1Pm+bRbFMLJROqR8VlK8HmsenL2WjrUIQ==", - "dev": true, - "requires": { - "babel-traverse": "^6.0.0", - "chalk": "^2.0.1", - "co": "^4.6.0", - "expect": "^23.4.0", - "is-generator-fn": "^1.0.0", - "jest-diff": "^23.2.0", - "jest-each": "^23.4.0", - "jest-matcher-utils": "^23.2.0", - "jest-message-util": "^23.4.0", - "jest-snapshot": "^23.4.2", - "jest-util": "^23.4.0", - "pretty-format": "^23.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "color-convert": "^1.9.0" + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "jest-leak-detector": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-23.2.0.tgz", - "integrity": "sha1-wonZYdxjjxQ1fU75bgQx7MGqN30=", - "dev": true, - "requires": { - "pretty-format": "^23.2.0" - } - }, - "jest-matcher-utils": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-23.2.0.tgz", - "integrity": "sha1-TUmB8jIT6Tnjzt8j3DTHR7WuGRM=", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "jest-get-type": "^22.1.0", - "pretty-format": "^23.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" } }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -4622,17 +7039,38 @@ } } }, - "jest-message-util": { - "version": "23.4.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-23.4.0.tgz", - "integrity": "sha1-F2EMUJQjSVCNAaPR4L2iwHkIap8=", + "jest-mock": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.8.0.tgz", + "integrity": "sha512-6kWugwjGjJw+ZkK4mDa0Df3sDlUTsV47MSrT0nGQ0RBWJbpODDQ8MHDVtGtUYBne3IwZUhtB7elxHspU79WH3A==", + "dev": true, + "requires": { + "@jest/types": "^24.8.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", + "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", + "dev": true + }, + "jest-regex-util": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.3.0.tgz", + "integrity": "sha512-tXQR1NEOyGlfylyEjg1ImtScwMq8Oh3iJbGTjN7p0J23EuVX1MA8rwU69K4sLbCmwzgCUbVkm0FkSF9TdzOhtg==", + "dev": true + }, + "jest-resolve": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.8.0.tgz", + "integrity": "sha512-+hjSzi1PoRvnuOICoYd5V/KpIQmkAsfjFO71458hQ2Whi/yf1GDeBOFj8Gxw4LrApHsVJvn5fmjcPdmoUHaVKw==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0-beta.35", + "@jest/types": "^24.8.0", + "browser-resolve": "^1.11.3", "chalk": "^2.0.1", - "micromatch": "^2.3.11", - "slash": "^1.0.0", - "stack-utils": "^1.0.1" + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" }, "dependencies": { "ansi-styles": { @@ -4645,9 +7083,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -4656,9 +7094,9 @@ } }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -4666,27 +7104,42 @@ } } }, - "jest-mock": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-23.2.0.tgz", - "integrity": "sha1-rRxg8p6HGdR8JuETgJi20YsmETQ=", - "dev": true - }, - "jest-regex-util": { - "version": "23.3.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-23.3.0.tgz", - "integrity": "sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=", - "dev": true + "jest-resolve-dependencies": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.8.0.tgz", + "integrity": "sha512-hyK1qfIf/krV+fSNyhyJeq3elVMhK9Eijlwy+j5jqmZ9QsxwKBiP6qukQxaHtK8k6zql/KYWwCTQ+fDGTIJauw==", + "dev": true, + "requires": { + "@jest/types": "^24.8.0", + "jest-regex-util": "^24.3.0", + "jest-snapshot": "^24.8.0" + } }, - "jest-resolve": { - "version": "23.4.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-23.4.1.tgz", - "integrity": "sha512-VNk4YRNR5gsHhNS0Lp46/DzTT11e+ecbUC61ikE593cKbtdrhrMO+zXkOJaE8YDD5sHxH9W6OfssNn4FkZBzZQ==", + "jest-runner": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.8.0.tgz", + "integrity": "sha512-utFqC5BaA3JmznbissSs95X1ZF+d+4WuOWwpM9+Ak356YtMhHE/GXUondZdcyAAOTBEsRGAgH/0TwLzfI9h7ow==", "dev": true, "requires": { - "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", - "realpath-native": "^1.0.0" + "@jest/console": "^24.7.1", + "@jest/environment": "^24.8.0", + "@jest/test-result": "^24.8.0", + "@jest/types": "^24.8.0", + "chalk": "^2.4.2", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-config": "^24.8.0", + "jest-docblock": "^24.3.0", + "jest-haste-map": "^24.8.0", + "jest-jasmine2": "^24.8.0", + "jest-leak-detector": "^24.8.0", + "jest-message-util": "^24.8.0", + "jest-resolve": "^24.8.0", + "jest-runtime": "^24.8.0", + "jest-util": "^24.8.0", + "jest-worker": "^24.6.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" }, "dependencies": { "ansi-styles": { @@ -4699,9 +7152,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -4709,10 +7162,16 @@ "supports-color": "^5.3.0" } }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -4720,64 +7179,35 @@ } } }, - "jest-resolve-dependencies": { - "version": "23.4.2", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-23.4.2.tgz", - "integrity": "sha512-JUrU1/1mQAf0eKwKT4+RRnaqcw0UcRzRE38vyO+YnqoXUVidf646iuaKE+NG7E6Gb0+EVPOJ6TgqkaTPdQz78A==", - "dev": true, - "requires": { - "jest-regex-util": "^23.3.0", - "jest-snapshot": "^23.4.2" - } - }, - "jest-runner": { - "version": "23.4.2", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-23.4.2.tgz", - "integrity": "sha512-o+aEdDE7/Gyp8fLYEEf5B8aOUguz76AYcAMl5pueucey2Q50O8uUIXJ7zvt8O6OEJDztR3Kb+osMoh8MVIqgTw==", - "dev": true, - "requires": { - "exit": "^0.1.2", - "graceful-fs": "^4.1.11", - "jest-config": "^23.4.2", - "jest-docblock": "^23.2.0", - "jest-haste-map": "^23.4.1", - "jest-jasmine2": "^23.4.2", - "jest-leak-detector": "^23.2.0", - "jest-message-util": "^23.4.0", - "jest-runtime": "^23.4.2", - "jest-util": "^23.4.0", - "jest-worker": "^23.2.0", - "source-map-support": "^0.5.6", - "throat": "^4.0.0" - } - }, "jest-runtime": { - "version": "23.4.2", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-23.4.2.tgz", - "integrity": "sha512-qaUDOi7tcdDe3MH5g5ycEslTpx0voPZvzIYbKjvWxCzCL2JEemLM+7IEe0BeLi2v5wvb/uh3dkb2wQI67uPtCw==", + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.8.0.tgz", + "integrity": "sha512-Mq0aIXhvO/3bX44ccT+czU1/57IgOMyy80oM0XR/nyD5zgBcesF84BPabZi39pJVA6UXw+fY2Q1N+4BiVUBWOA==", "dev": true, "requires": { - "babel-core": "^6.0.0", - "babel-plugin-istanbul": "^4.1.6", + "@jest/console": "^24.7.1", + "@jest/environment": "^24.8.0", + "@jest/source-map": "^24.3.0", + "@jest/transform": "^24.8.0", + "@jest/types": "^24.8.0", + "@types/yargs": "^12.0.2", "chalk": "^2.0.1", - "convert-source-map": "^1.4.0", "exit": "^0.1.2", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.1.11", - "jest-config": "^23.4.2", - "jest-haste-map": "^23.4.1", - "jest-message-util": "^23.4.0", - "jest-regex-util": "^23.3.0", - "jest-resolve": "^23.4.1", - "jest-snapshot": "^23.4.2", - "jest-util": "^23.4.0", - "jest-validate": "^23.4.0", - "micromatch": "^2.3.11", - "realpath-native": "^1.0.0", - "slash": "^1.0.0", - "strip-bom": "3.0.0", - "write-file-atomic": "^2.1.0", - "yargs": "^11.0.0" + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "jest-config": "^24.8.0", + "jest-haste-map": "^24.8.0", + "jest-message-util": "^24.8.0", + "jest-mock": "^24.8.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.8.0", + "jest-snapshot": "^24.8.0", + "jest-util": "^24.8.0", + "jest-validate": "^24.8.0", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "strip-bom": "^3.0.0", + "yargs": "^12.0.2" }, "dependencies": { "ansi-styles": { @@ -4790,9 +7220,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -4800,10 +7230,36 @@ "supports-color": "^5.3.0" } }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -4812,26 +7268,28 @@ } }, "jest-serializer": { - "version": "23.0.1", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-23.0.1.tgz", - "integrity": "sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU=", + "version": "24.4.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.4.0.tgz", + "integrity": "sha512-k//0DtglVstc1fv+GY/VHDIjrtNjdYvYjMlbLUed4kxrE92sIUewOi5Hj3vrpB8CXfkJntRPDRjCrCvUhBdL8Q==", "dev": true }, "jest-snapshot": { - "version": "23.4.2", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-23.4.2.tgz", - "integrity": "sha512-rCBxIURDlVEW1gJgJSpo8l2F2gFwp9U7Yb3CmcABUpmQ8NASpb6LJkEvtcQifAYSi22OL44TSuanq1G6x1GJwg==", + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.8.0.tgz", + "integrity": "sha512-5ehtWoc8oU9/cAPe6fez6QofVJLBKyqkY2+TlKTOf0VllBB/mqUNdARdcjlZrs9F1Cv+/HKoCS/BknT0+tmfPg==", "dev": true, "requires": { - "babel-types": "^6.0.0", + "@babel/types": "^7.0.0", + "@jest/types": "^24.8.0", "chalk": "^2.0.1", - "jest-diff": "^23.2.0", - "jest-matcher-utils": "^23.2.0", - "jest-message-util": "^23.4.0", - "jest-resolve": "^23.4.1", + "expect": "^24.8.0", + "jest-diff": "^24.8.0", + "jest-matcher-utils": "^24.8.0", + "jest-message-util": "^24.8.0", + "jest-resolve": "^24.8.0", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "pretty-format": "^23.2.0", + "pretty-format": "^24.8.0", "semver": "^5.5.0" }, "dependencies": { @@ -4845,9 +7303,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -4856,9 +7314,9 @@ } }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -4867,18 +7325,22 @@ } }, "jest-util": { - "version": "23.4.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-23.4.0.tgz", - "integrity": "sha1-TQY8uSe68KI4Mf9hvsLLv0l5NWE=", + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.8.0.tgz", + "integrity": "sha512-DYZeE+XyAnbNt0BG1OQqKy/4GVLPtzwGx5tsnDrFcax36rVE3lTA5fbvgmbVPUZf9w77AJ8otqR4VBbfFJkUZA==", "dev": true, "requires": { - "callsites": "^2.0.0", + "@jest/console": "^24.7.1", + "@jest/fake-timers": "^24.8.0", + "@jest/source-map": "^24.3.0", + "@jest/test-result": "^24.8.0", + "@jest/types": "^24.8.0", + "callsites": "^3.0.0", "chalk": "^2.0.1", - "graceful-fs": "^4.1.11", - "is-ci": "^1.0.10", - "jest-message-util": "^23.4.0", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", "mkdirp": "^0.5.1", - "slash": "^1.0.0", + "slash": "^2.0.0", "source-map": "^0.6.0" }, "dependencies": { @@ -4892,15 +7354,15 @@ } }, "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -4908,6 +7370,18 @@ "supports-color": "^5.3.0" } }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -4915,9 +7389,9 @@ "dev": true }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -4926,15 +7400,17 @@ } }, "jest-validate": { - "version": "23.4.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-23.4.0.tgz", - "integrity": "sha1-2W7t4B7wOskJwAnpyORVGX1IwgE=", + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.8.0.tgz", + "integrity": "sha512-+/N7VOEMW1Vzsrk3UWBDYTExTPwf68tavEPKDnJzrC6UlHtUDU/fuEdXqFoHzv9XnQ+zW6X3qMZhJ3YexfeLDA==", "dev": true, "requires": { + "@jest/types": "^24.8.0", + "camelcase": "^5.0.0", "chalk": "^2.0.1", - "jest-get-type": "^22.1.0", + "jest-get-type": "^24.8.0", "leven": "^2.1.0", - "pretty-format": "^23.2.0" + "pretty-format": "^24.8.0" }, "dependencies": { "ansi-styles": { @@ -4947,9 +7423,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -4958,9 +7434,9 @@ } }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -4969,13 +7445,17 @@ } }, "jest-watcher": { - "version": "23.4.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-23.4.0.tgz", - "integrity": "sha1-0uKM50+NrWxq/JIrksq+9u0FyRw=", + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.8.0.tgz", + "integrity": "sha512-SBjwHt5NedQoVu54M5GEx7cl7IGEFFznvd/HNT8ier7cCAx/Qgu9ZMlaTQkvK22G1YOpcWBLQPFSImmxdn3DAw==", "dev": true, "requires": { + "@jest/test-result": "^24.8.0", + "@jest/types": "^24.8.0", + "@types/yargs": "^12.0.9", "ansi-escapes": "^3.0.0", "chalk": "^2.0.1", + "jest-util": "^24.8.0", "string-length": "^2.0.0" }, "dependencies": { @@ -4989,9 +7469,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -5000,9 +7480,9 @@ } }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -5011,12 +7491,24 @@ } }, "jest-worker": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-23.2.0.tgz", - "integrity": "sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=", + "version": "24.6.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.6.0.tgz", + "integrity": "sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ==", "dev": true, "requires": { - "merge-stream": "^1.0.1" + "merge-stream": "^1.0.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "js-tokens": { @@ -5026,9 +7518,9 @@ "dev": true }, "js-yaml": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", - "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -5039,8 +7531,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true + "dev": true }, "jsdom": { "version": "11.12.0", @@ -5164,25 +7655,18 @@ } }, "kleur": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-2.0.1.tgz", - "integrity": "sha512-Zq/jyANIJ2uX8UZjWlqLwbyhcxSXJtT/Y89lClyeZd3l++3ztL1I5SSCYrbcbwSunTjC88N3WuMk0kRDQD6gzA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true, - "optional": true - }, "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", "dev": true, "requires": { - "invert-kv": "^1.0.0" + "invert-kv": "^2.0.0" } }, "left-pad": { @@ -5230,9 +7714,9 @@ } }, "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, "lodash.sortby": { @@ -5241,12 +7725,6 @@ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, "loose-envify": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", @@ -5283,6 +7761,30 @@ } } }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + } + } + }, "makeerror": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", @@ -5292,6 +7794,15 @@ "tmpl": "1.0.x" } }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -5308,9 +7819,9 @@ } }, "marked": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", - "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.4.0.tgz", + "integrity": "sha512-tMsdNBgOsrUophCAFQl0XPe6Zqk/uy9gnue+jIIKhykO51hxyu6uNx7zBPy0+y/WKYVZZMspV9YeXLNdKk+iYw==", "dev": true }, "math-random": { @@ -5320,20 +7831,24 @@ "dev": true }, "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + }, + "dependencies": { + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + } } }, - "merge": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", - "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=", - "dev": true - }, "merge-stream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", @@ -5365,18 +7880,18 @@ } }, "mime-db": { - "version": "1.35.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", - "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==", + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", "dev": true }, "mime-types": { - "version": "2.1.19", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", - "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", "dev": true, "requires": { - "mime-db": "~1.35.0" + "mime-db": "1.40.0" } }, "mimic-fn": { @@ -5481,13 +7996,6 @@ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, - "nan": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "dev": true, - "optional": true - }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -5533,10 +8041,16 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "neo-async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", + "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", + "dev": true + }, "nice-try": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", - "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, "node-int64": { @@ -5545,14 +8059,21 @@ "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", "dev": true }, + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", + "dev": true + }, "node-notifier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.2.1.tgz", - "integrity": "sha512-MIBs+AAd6dJ2SklbbE8RUDRlIVhU8MaNLh1A9SUZDUHPiZkWLFde6UNwG41yQHZEToHgJMXqyVZ9UcS/ReOVTg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.0.tgz", + "integrity": "sha512-SUDEb+o71XR5lXSTyivXd9J7fCloE3SyP4lSgt3lU2oSANiox+SxlNRGPjDKrwU1YN3ix2KN/VGGCg0t01rttQ==", "dev": true, "requires": { "growly": "^1.3.0", - "semver": "^5.4.1", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", "shellwords": "^0.1.1", "which": "^1.3.0" } @@ -5594,15 +8115,15 @@ "dev": true }, "nwsapi": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.0.8.tgz", - "integrity": "sha512-7RZ+qbFGiVc6v14Y8DSZjPN1wZPOaMbiiP4tzf5eNuyOITAeOIA3cMhjuKUypVIqBgCSg1KaSyAv8Ocq/0ZJ1A==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz", + "integrity": "sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw==", "dev": true }, "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true }, "object-assign": { @@ -5750,14 +8271,14 @@ "dev": true }, "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" } }, "os-tmpdir": { @@ -5766,12 +8287,33 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "dev": true, + "requires": { + "p-reduce": "^1.0.0" + } + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true + }, "p-limit": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", @@ -5790,12 +8332,35 @@ "p-limit": "^1.1.0" } }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", + "dev": true + }, "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + } + } + }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", @@ -5901,6 +8466,15 @@ "pinkie": "^2.0.0" } }, + "pirates": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", + "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", + "dev": true, + "requires": { + "node-modules-regexp": "^1.0.0" + } + }, "pkg-conf": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", @@ -6013,19 +8587,21 @@ "dev": true }, "pretty-format": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.2.0.tgz", - "integrity": "sha1-OwqqY8AYpTWDNzwcs6XZbMXoMBc=", + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.8.0.tgz", + "integrity": "sha512-P952T7dkrDEplsR+TuY7q3VXDae5Sr7zmQb12JU/NDQa/3CH7/QW0yvqLcGN6jL+zQFKaoJcPc+yJxMTGmosqw==", "dev": true, "requires": { - "ansi-regex": "^3.0.0", - "ansi-styles": "^3.2.0" + "@jest/types": "^24.8.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "ansi-styles": { @@ -6064,13 +8640,13 @@ "dev": true }, "prompts": { - "version": "0.1.14", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-0.1.14.tgz", - "integrity": "sha512-rxkyiE9YH6zAz/rZpywySLKkpaj0NMVyNw1qhsubdbjjSgcayjTShDreZGlFMcGSu5sab3bAKPfFk78PB90+8w==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.0.4.tgz", + "integrity": "sha512-HTzM3UWp/99A0gk51gAegwo1QRYA7xjcZufMNe33rCclFszUYAuHe1fIN/3ZmiHeGPkUsNaRyQm1hHOfM0PKxA==", "dev": true, "requires": { - "kleur": "^2.0.1", - "sisteransi": "^0.1.1" + "kleur": "^3.0.2", + "sisteransi": "^1.0.0" } }, "prop-types": { @@ -6090,11 +8666,21 @@ "dev": true }, "psl": { - "version": "1.1.29", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", "dev": true }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -6107,6 +8693,12 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", + "dev": true + }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", @@ -6156,9 +8748,9 @@ } }, "realpath-native": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.0.1.tgz", - "integrity": "sha512-W14EcXuqUvKP8dkWkD7B95iMy77lpMnlFXbbk409bQtNCbeu0kvRE5reo+yIZ3JXxg6frbGsz2DLQ39lrCB40g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", "dev": true, "requires": { "util.promisify": "^1.0.0" @@ -6215,19 +8807,10 @@ "safe-regex": "^1.1.0" } }, - "regexp.prototype.flags": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", - "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", - "dev": true, - "requires": { - "define-properties": "^1.1.2" - } - }, "regexpp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.0.tgz", - "integrity": "sha512-g2FAVtR8Uh8GO1Nv5wpxW7VFVwHcCEr4wyA8/MHiRkO8uHoR5ntAA8Uq3P1vvMTX/BeQiRVSpDGLd+Wn5HNOTA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true }, "regexpu-core": { @@ -6284,31 +8867,31 @@ } }, "request": { - "version": "2.87.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", - "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "dev": true, "requires": { "aws-sign2": "~0.7.0", - "aws4": "^1.6.0", + "aws4": "^1.8.0", "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.1", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", "forever-agent": "~0.6.1", - "form-data": "~2.3.1", - "har-validator": "~5.0.3", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.17", - "oauth-sign": "~0.8.2", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", "performance-now": "^2.1.0", - "qs": "~6.5.1", - "safe-buffer": "^5.1.1", - "tough-cookie": "~2.3.3", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", "tunnel-agent": "^0.6.0", - "uuid": "^3.1.0" + "uuid": "^3.3.2" }, "dependencies": { "punycode": { @@ -6317,35 +8900,42 @@ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "dev": true, "requires": { + "psl": "^1.1.24", "punycode": "^1.4.1" } } } }, "request-promise-core": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", - "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", "dev": true, "requires": { - "lodash": "^4.13.1" + "lodash": "^4.17.11" } }, "request-promise-native": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", - "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", + "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", "dev": true, "requires": { - "request-promise-core": "1.1.1", - "stealthy-require": "^1.1.0", - "tough-cookie": ">=2.3.3" + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" } }, "require-directory": { @@ -6355,9 +8945,9 @@ "dev": true }, "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, "require-relative": { @@ -6425,20 +9015,10 @@ } }, "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "optional": true, - "requires": { - "align-text": "^0.1.1" - } + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true }, "rimraf": { "version": "2.6.2", @@ -6478,20 +9058,296 @@ "rollup-pluginutils": "^2.0.1" }, "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, "estree-walker": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz", - "integrity": "sha1-5rGlHPcpJSTnI3wxLl/mZgwc4ao=", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.0.tgz", + "integrity": "sha512-peq1RfVAVzr3PU/jL31RaOjUKLoZJpObQWJJ+LgfcxDUifyLZ1RjPQZTl0pzj2uJ45b7A7XpyppXvxdEqzo4rw==", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, "rollup-pluginutils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz", - "integrity": "sha1-fslbNXP2VDpGpkYb2afFRFJdD8A=", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.6.0.tgz", + "integrity": "sha512-aGQwspEF8oPKvg37u3p7h0cYNwmJR1sCBMZGZ5b9qy8HGtETknqjzcxrDRrcAnJNXN18lBH4Q9vZYth/p4n8jQ==", "dev": true, "requires": { - "estree-walker": "^0.3.0", - "micromatch": "^2.3.11" + "estree-walker": "^0.6.0", + "micromatch": "^3.1.10" + }, + "dependencies": { + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } } } } @@ -6508,12 +9364,265 @@ "rollup-pluginutils": "^2.0.1" }, "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, "estree-walker": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.5.2.tgz", "integrity": "sha512-XpCnW/AE10ws/kDAs37cngSkvgIR8aN3G0MS85m7dUpuK2EREo9VJ00uvw6Dg/hXEpfsE1I1TvJOJr+Z+TL+ig==", "dev": true }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, "resolve": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", @@ -6524,13 +9633,42 @@ } }, "rollup-pluginutils": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.3.1.tgz", - "integrity": "sha512-JZS8aJMHEHhqmY2QVPMXwKP6lsD1ShkrcGYjhAIvqKKdXQyPHw/9NF0tl3On/xOJ4ACkxfeG7AF+chfCN1NpBg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.6.0.tgz", + "integrity": "sha512-aGQwspEF8oPKvg37u3p7h0cYNwmJR1sCBMZGZ5b9qy8HGtETknqjzcxrDRrcAnJNXN18lBH4Q9vZYth/p4n8jQ==", "dev": true, "requires": { - "estree-walker": "^0.5.2", - "micromatch": "^2.3.11" + "estree-walker": "^0.6.0", + "micromatch": "^3.1.10" + }, + "dependencies": { + "estree-walker": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.0.tgz", + "integrity": "sha512-peq1RfVAVzr3PU/jL31RaOjUKLoZJpObQWJJ+LgfcxDUifyLZ1RjPQZTl0pzj2uJ45b7A7XpyppXvxdEqzo4rw==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } } } } @@ -6544,20 +9682,296 @@ "rollup-pluginutils": "^2.2.0" }, "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, "estree-walker": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.5.2.tgz", - "integrity": "sha512-XpCnW/AE10ws/kDAs37cngSkvgIR8aN3G0MS85m7dUpuK2EREo9VJ00uvw6Dg/hXEpfsE1I1TvJOJr+Z+TL+ig==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.0.tgz", + "integrity": "sha512-peq1RfVAVzr3PU/jL31RaOjUKLoZJpObQWJJ+LgfcxDUifyLZ1RjPQZTl0pzj2uJ45b7A7XpyppXvxdEqzo4rw==", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, "rollup-pluginutils": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.3.0.tgz", - "integrity": "sha512-xB6hsRsjdJdIYWEyYUJy/3ki5g69wrf0luHPGNK3ZSocV6HLNfio59l3dZ3TL4xUwEKgROhFi9jOCt6c5gfUWw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.6.0.tgz", + "integrity": "sha512-aGQwspEF8oPKvg37u3p7h0cYNwmJR1sCBMZGZ5b9qy8HGtETknqjzcxrDRrcAnJNXN18lBH4Q9vZYth/p4n8jQ==", "dev": true, "requires": { - "estree-walker": "^0.5.2", - "micromatch": "^2.3.11" + "estree-walker": "^0.6.0", + "micromatch": "^3.1.10" + }, + "dependencies": { + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } } } } @@ -6602,28 +10016,304 @@ "rollup-pluginutils": "^2.0.1" }, "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, "estree-walker": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz", - "integrity": "sha1-5rGlHPcpJSTnI3wxLl/mZgwc4ao=", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.0.tgz", + "integrity": "sha512-peq1RfVAVzr3PU/jL31RaOjUKLoZJpObQWJJ+LgfcxDUifyLZ1RjPQZTl0pzj2uJ45b7A7XpyppXvxdEqzo4rw==", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, "rollup-pluginutils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz", - "integrity": "sha1-fslbNXP2VDpGpkYb2afFRFJdD8A=", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.6.0.tgz", + "integrity": "sha512-aGQwspEF8oPKvg37u3p7h0cYNwmJR1sCBMZGZ5b9qy8HGtETknqjzcxrDRrcAnJNXN18lBH4Q9vZYth/p4n8jQ==", "dev": true, "requires": { - "estree-walker": "^0.3.0", - "micromatch": "^2.3.11" + "estree-walker": "^0.6.0", + "micromatch": "^3.1.10" + }, + "dependencies": { + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } } } } }, "rsvp": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", - "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.4.tgz", + "integrity": "sha512-6FomvYPfs+Jy9TfXmBpBuMWNH94SgCsZmJKcanySzgNNP6LjWxBvyLTa9KaMfDDM5oxRfrKDB0r/qeRsLwnBfA==", "dev": true }, "run-async": { @@ -6657,12 +10347,12 @@ } }, "rxjs": { - "version": "5.5.11", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.11.tgz", - "integrity": "sha512-3bjO7UwWfA2CV7lmwYMBzj4fQ6Cq+ftHc2MvUe+WMS7wcdJ1LosDWmdjPQanYp2dBRj572p7PeU81JUxHKOcBA==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.1.tgz", + "integrity": "sha512-y0j31WJc83wPu31vS1VlAFW5JGrnGC+j+TtGAa1fRQphy48+fDYiDmX8tjGloToEsMkxnouOg/1IzXGKkJnZMg==", "dev": true, "requires": { - "symbol-observable": "1.0.1" + "tslib": "^1.9.0" } }, "safe-buffer": { @@ -6687,20 +10377,20 @@ "dev": true }, "sane": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/sane/-/sane-2.5.2.tgz", - "integrity": "sha1-tNwYYcIbQn6SlQej51HiosuKs/o=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", "dev": true, "requires": { + "@cnakazawa/watch": "^1.0.3", "anymatch": "^2.0.0", - "capture-exit": "^1.2.0", - "exec-sh": "^0.2.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", "fb-watchman": "^2.0.0", - "fsevents": "^1.2.3", "micromatch": "^3.1.4", "minimist": "^1.1.1", - "walker": "~1.0.5", - "watch": "~0.18.0" + "walker": "~1.0.5" }, "dependencies": { "anymatch": { @@ -6998,7 +10688,7 @@ "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, "semver": { @@ -7070,9 +10760,9 @@ } }, "shelljs": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", - "integrity": "sha512-YA/iYtZpzFe5HyWVGrb02FjPxc4EMCfpoU/Phg9fQoyMC72u9598OUBrsU8IrtwAKG0tO8IYaqbaLIw+k3IRGA==", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", + "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", "dev": true, "requires": { "glob": "^7.0.0", @@ -7083,7 +10773,7 @@ "shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", - "integrity": "sha1-1rkYHBpI05cyTISHHvvPxz/AZUs=", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", "dev": true }, "signal-exit": { @@ -7099,9 +10789,9 @@ "dev": true }, "sisteransi": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-0.1.1.tgz", - "integrity": "sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.0.tgz", + "integrity": "sha512-N+z4pHB4AmUv0SjveWRd6q1Nj5w62m5jodv+GD8lvmbY/83T/rpbJGZOnK5T149OldDj4Db07BSv9xY4K6NTPQ==", "dev": true }, "slash": { @@ -7322,9 +11012,9 @@ "dev": true }, "sshpk": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", - "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", "dev": true, "requires": { "asn1": "~0.2.3", @@ -7339,9 +11029,9 @@ } }, "stack-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.1.tgz", - "integrity": "sha1-1PM6tU6OOHeLDKXP07OvsS22hiA=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", + "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", "dev": true }, "standard": { @@ -7619,19 +11309,6 @@ } } }, - "string.prototype.matchall": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-2.0.0.tgz", - "integrity": "sha512-WoZ+B2ypng1dp4iFLF2kmZlwwlE19gmjgKuhL1FJfDgCREWb3ye3SDVHSzLH6bxfnvYmkCxbzkmWcQZHA4P//Q==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.10.0", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "regexp.prototype.flags": "^1.2.0" - } - }, "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", @@ -7691,12 +11368,6 @@ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, - "symbol-observable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", - "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", - "dev": true - }, "symbol-tree": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", @@ -7706,406 +11377,173 @@ "table": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha1-ozRHN1OR52atNNNIbm4q7chNLjY=", - "dev": true, - "requires": { - "ajv": "^5.2.3", - "ajv-keywords": "^2.1.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", - "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "supports-color": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", - "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "test-exclude": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.1.tgz", - "integrity": "sha512-qpqlP/8Zl+sosLxBcVKl9vYy26T9NPalxSzzCP/OY6K7j938ui2oKgo+kRZYfxAeIpLqpbVnsHq1tyV70E4lWQ==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "micromatch": "^3.1.8", - "object-assign": "^4.1.0", - "read-pkg-up": "^1.0.1", - "require-main-filename": "^1.0.1" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "integrity": "sha1-ozRHN1OR52atNNNIbm4q7chNLjY=", + "dev": true, + "requires": { + "ajv": "^5.2.3", + "ajv-keywords": "^2.1.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", "dev": true, "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "has-flag": "^3.0.0" } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + } + } + }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "dev": true, + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "locate-path": "^3.0.0" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" } }, - "is-number": { + "locate-path": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" } }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "p-try": "^2.0.0" } }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "p-limit": "^2.0.0" } }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { - "pinkie-promise": "^2.0.0" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" } }, "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "pify": "^3.0.0" } }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, "requires": { - "load-json-file": "^1.0.0", + "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "path-type": "^3.0.0" } }, "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" } } } @@ -8198,21 +11636,13 @@ } }, "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dev": true, "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } + "psl": "^1.1.28", + "punycode": "^2.1.1" } }, "tr46": { @@ -8241,6 +11671,12 @@ "lodash": "^4.17.10" } }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "dev": true + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -8254,8 +11690,7 @@ "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true + "dev": true }, "type-check": { "version": "0.3.2", @@ -8279,34 +11714,34 @@ "dev": true }, "typedoc": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.11.1.tgz", - "integrity": "sha512-jdNIoHm5wkZqxQTe/g9AQ3LKnZyrzHXqu6A/c9GUOeJyBWLxNr7/Dm3rwFvLksuxRNwTvY/0HRDU9sJTa9WQSg==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.14.2.tgz", + "integrity": "sha512-aEbgJXV8/KqaVhcedT7xG6d2r+mOvB5ep3eIz1KuB5sc4fDYXcepEEMdU7XSqLFO5hVPu0nllHi1QxX2h/QlpQ==", "dev": true, "requires": { - "@types/fs-extra": "5.0.1", - "@types/handlebars": "4.0.36", - "@types/highlight.js": "9.12.2", - "@types/lodash": "4.14.104", - "@types/marked": "0.3.0", + "@types/fs-extra": "^5.0.3", + "@types/handlebars": "^4.0.38", + "@types/highlight.js": "^9.12.3", + "@types/lodash": "^4.14.110", + "@types/marked": "^0.4.0", "@types/minimatch": "3.0.3", - "@types/shelljs": "0.7.8", - "fs-extra": "^5.0.0", + "@types/shelljs": "^0.8.0", + "fs-extra": "^7.0.0", "handlebars": "^4.0.6", - "highlight.js": "^9.0.0", - "lodash": "^4.17.5", - "marked": "^0.3.17", + "highlight.js": "^9.13.1", + "lodash": "^4.17.10", + "marked": "^0.4.0", "minimatch": "^3.0.0", "progress": "^2.0.0", - "shelljs": "^0.8.1", + "shelljs": "^0.8.2", "typedoc-default-themes": "^0.5.0", - "typescript": "2.7.2" + "typescript": "3.2.x" }, "dependencies": { "fs-extra": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", - "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -8314,16 +11749,10 @@ "universalify": "^0.1.0" } }, - "lodash": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", - "dev": true - }, "typescript": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.7.2.tgz", - "integrity": "sha512-p5TCYZDAO0m4G344hD+wx/LATebLWZNkkh2asWUFqSsD2OrDNhbAHuSjobrmsUmdzjJjEeZVU9g1h3O6vpstnw==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.4.tgz", + "integrity": "sha512-0RNDbSdEokBeEAkgNbxJ+BLwSManFy9TeXz8uW+48j/xhEXv1ePME60olyzw2XzUqUBNAYFeJadIqAgNqIACwg==", "dev": true } } @@ -8364,13 +11793,6 @@ } } }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, - "optional": true - }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", @@ -8552,24 +11974,6 @@ "makeerror": "1.0.x" } }, - "watch": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/watch/-/watch-0.18.0.tgz", - "integrity": "sha1-KAlUdsbffJDJYxOJkMClQj60uYY=", - "dev": true, - "requires": { - "exec-sh": "^0.2.0", - "minimist": "^1.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, "webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", @@ -8577,18 +11981,29 @@ "dev": true }, "whatwg-encoding": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.3.tgz", - "integrity": "sha512-jLBwwKUhi8WtBfsMQlL4bUUcT8sMkAtQinscJAe/M4KHCkHuUJAF6vuB0tueNIw4c8ziO6AkRmgY+jL3a0iiPw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", "dev": true, "requires": { - "iconv-lite": "0.4.19" + "iconv-lite": "0.4.24" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } } }, "whatwg-mimetype": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.1.0.tgz", - "integrity": "sha512-FKxhYLytBQiUKjkYteN71fAUA3g6KpNXoho1isLiLSB3N1G4F35Q5vUxWfKFhBwi5IWF27VE6WxhrnnC+m0Mew==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", "dev": true }, "whatwg-url": { @@ -8617,13 +12032,6 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true, - "optional": true - }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -8678,9 +12086,9 @@ } }, "write-file-atomic": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", - "integrity": "sha1-H/YVdcLipOjlENb6TiQ8zhg5mas=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", "dev": true, "requires": { "graceful-fs": "^4.1.11", @@ -8710,9 +12118,9 @@ "dev": true }, "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, "yallist": { @@ -8722,32 +12130,84 @@ "dev": true }, "yargs": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", - "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", "dev": true, "requires": { "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", + "os-locale": "^3.0.0", "require-directory": "^2.1.1", "require-main-filename": "^1.0.1", "set-blocking": "^2.0.0", "string-width": "^2.0.0", "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^9.0.2" + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + } } }, "yargs-parser": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", - "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", "dev": true, "requires": { - "camelcase": "^4.1.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } diff --git a/package.json b/package.json index 58a4d7991..34d0a5ab3 100644 --- a/package.json +++ b/package.json @@ -73,10 +73,10 @@ "chai": "^4.1.1", "chroma-js": "^1.3.7", "cpx": "^1.5.0", - "eslint": "^5.3.0", + "eslint": "^5.16.0", "eslint-plugin-import": "^2.13.0", "eslint-plugin-react": "^7.10.0", - "jest": "^23.4.2", + "jest": "^24.8.0", "mocha": "^5.2.0", "promise-polyfill": "^8.0.0", "rollup": "^0.63.5", @@ -93,7 +93,7 @@ "standard": "^11.0.1", "three": "^0.95.0", "ts-jest": "^23.1.3", - "typedoc": "^0.11.1", + "typedoc": "^0.14.2", "typescript": "^3.0.1", "uglify-js": "^3.4.6" }, diff --git a/src/controls/mouse-actions.ts b/src/controls/mouse-actions.ts index 00931bae4..256de7559 100644 --- a/src/controls/mouse-actions.ts +++ b/src/controls/mouse-actions.ts @@ -177,13 +177,6 @@ class MouseActions { stage.trackballControls.rotateComponent(dx, dy) } - static drawDragBox (stage: Stage, dx: number, dy: number) { - - } - - static updateDragBox (stage: Stage, dx: number, dy: number) { - - } /** * Move picked component based on mouse coordinate changes * @param {Stage} stage @@ -192,18 +185,7 @@ class MouseActions { * @return {undefined} */ static moveComponentDrag (stage: Stage, dx: number, dy: number) { - return; // TODO** - } - - /** - * Pick component based on mouse coordinate changes - * @param {Stage} stage - * @param {Number} dx - amount to select in x direction - * @param {Number} dy - amount to select in y direction - * @return {undefined} - */ - static lassoComponentDrag (stage: Stage, dx: number, dy: number) { - return; // TODO** + stage.trackballControls.translateAtoms(dx, dy) } /** @@ -238,6 +220,8 @@ class MouseActions { } } + + static measurePick (stage: Stage, pickingProxy: PickingProxy) { if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) { const atom = pickingProxy.atom || pickingProxy.closestBondAtom @@ -262,7 +246,7 @@ class MouseActions { } } - static selectPickAll (stage: Stage, pickingProxies: PickingProxy[]) { + static selectPickAll (stage: Stage, pickingProxies: PickingProxy[], x:number, y:number) { let components: StructureComponent[] = [] let picked: AtomProxy[][] = [] @@ -287,6 +271,8 @@ class MouseActions { for (var i = 0; i < components.length; i++) { components[i].selectedPick(picked[i]) } + + stage.dragSelection.moveSelection(x, y) } static clearSelect (stage: Stage) { @@ -295,6 +281,25 @@ class MouseActions { }, "structure") } + static onSelectDown (stage: Stage, x: number, y: number) { + const ds = stage.dragSelection + const sp = stage.getParameters() as any + if (sp.dragSelection) { + ds.createSelection(x, y) + } else { + ds.removeSelection() + } + } + + static onSelectDragXY (stage: Stage, x: number, y: number) { + const ds = stage.dragSelection + ds.moveSelection(x, y) + } + + static onSelectUp (stage: Stage) { + stage.dragSelection.removeSelection() + } + } type MouseActionPreset = [ string, MouseActionCallback ][] @@ -358,7 +363,7 @@ export const MouseActionPresets = { [ 'drag-left', MouseActions.rotateDrag ], [ 'drag-right', MouseActions.panDrag ], - [ 'drag-ctrl-left', MouseActions.rotatePositionComponentDrag ], + [ 'drag-ctrl-left', MouseActions.rotateComponentDrag ], [ 'drag-ctrl-right', MouseActions.moveComponentDrag ], [ 'drag-shift-left', MouseActions.selectPickAll ], [ 'drag-middle', MouseActions.zoomFocusDrag ], diff --git a/src/controls/trackball-controls.ts b/src/controls/trackball-controls.ts index 3b7f02852..bbe658460 100644 --- a/src/controls/trackball-controls.ts +++ b/src/controls/trackball-controls.ts @@ -13,6 +13,7 @@ import Viewer from '../viewer/viewer' import ViewerControls from './viewer-controls' import AtomProxy from '../proxy/atom-proxy'; import Component from '../component/component'; +import StructureComponent from '../component/structure-component'; const tmpRotateXMatrix = new Matrix4() const tmpRotateYMatrix = new Matrix4() @@ -118,6 +119,45 @@ class TrackballControls { this.component.updateRepresentations({ 'position': true }) } + private _translateAtom (panMatrix: Matrix4, atom: AtomProxy, x: number, y: number) { + let _tmpAtomVector = new Vector3(); + let _tmpPanVector = new Vector3(); + atom.positionToVector3(_tmpAtomVector) + _tmpAtomVector.add(this.viewer.translationGroup.position) + _tmpAtomVector.applyMatrix4(this.viewer.rotationGroup.matrix) + + let scaleFactor = this.controls.getCanvasScaleFactor(_tmpAtomVector.z) + _tmpPanVector.set(x, y, 0) + _tmpPanVector.multiplyScalar(this.panSpeed * scaleFactor) + _tmpPanVector.applyMatrix4(panMatrix) + + + atom.positionAdd(_tmpPanVector) + } + + private _translateComponent (comp: StructureComponent, x: number, y: number) { + + let _tmpPanMatrix = new Matrix4(); + _tmpPanMatrix.extractRotation(comp.transform) + _tmpPanMatrix.premultiply(this.viewer.rotationGroup.matrix) + _tmpPanMatrix.getInverse(_tmpPanMatrix) + + for (var j = 0; j < comp.selectedAtomIndices.list.length; j++) { + let i = comp.selectedAtomIndices.list[j] + let atom = comp.structure.getAtomProxy(i) + this._translateAtom(_tmpPanMatrix, atom, x, y) + } + + comp.updateRepresentations({'position': true}) + } + + translateAtoms (x: number, y: number) { + let _move = this._translateComponent + this.stage.eachComponent(function (sc: StructureComponent) { + _move(sc, x, y) + }) + } + rotate (x: number, y: number) { const [ dx, dy ] = this._getRotateXY(x, y) @@ -153,6 +193,7 @@ class TrackballControls { this.component.quaternion.premultiply(tmpRotateQuaternion) this.component.updateMatrix() } + } export default TrackballControls diff --git a/src/geometry/shape-2d.ts b/src/geometry/shape-2d.ts deleted file mode 100644 index bd51b1bff..000000000 --- a/src/geometry/shape-2d.ts +++ /dev/null @@ -1,240 +0,0 @@ -/** - * @file Shape-2D - * @author Lily Wang - * @private - */ - - -import { Box2, Vector2, Color } from 'three' - -import { createParams, ensureFloat32Array, getUintArray } from '../utils' -import { - ArrowPrimitive, BoxPrimitive, ConePrimitive, CylinderPrimitive, EllipsoidPrimitive, - OctahedronPrimitive, SpherePrimitive, TetrahedronPrimitive, TextPrimitive, - TorusPrimitive, PointPrimitive, WidelinePrimitive -} from './primitive' -import { MeshPicker } from '../utils/picker' -import Buffer from '../buffer/buffer' -import MeshBuffer from '../buffer/mesh-buffer' -import { TextBufferParameters } from '../buffer/text-buffer' - -const tmpBox = new Box3() - -const Primitives = [ - ArrowPrimitive, BoxPrimitive, ConePrimitive, CylinderPrimitive, - EllipsoidPrimitive, OctahedronPrimitive, SpherePrimitive, TetrahedronPrimitive, - TextPrimitive, TorusPrimitive, PointPrimitive, WidelinePrimitive -] - -export const ShapeDefaultParameters = { - aspectRatio: 1.5, - sphereDetail: 2, - radialSegments: 50, - disableImpostor: false, - openEnded: false, - dashedCylinder: false, - labelParams: {} as Partial, - pointSize: 2, - sizeAttenuation: false, - useTexture: true, - lineWidth: 2 -} -export type ShapeParameters = typeof ShapeDefaultParameters - -/** - * Class for building custom shapes. - * - * @example - * var shape = new NGL.Shape('shape', { disableImpostor: true }); - * shape.addSphere([ 0, 0, 9 ], [ 1, 0, 0 ], 1.5 ); - * shape.addEllipsoid([ 6, 0, 0 ], [ 1, 0, 0 ], 1.5, [ 3, 0, 0 ], [ 0, 2, 0 ]); - * shape.addCylinder([ 0, 2, 7 ], [ 0, 0, 9 ], [ 1, 1, 0 ], 0.5); - * shape.addCone([ 0, 2, 7 ], [ 0, 3, 3 ], [ 1, 1, 0 ], 1.5); - * shape.addArrow([ 1, 2, 7 ], [ 30, 3, 3 ], [ 1, 0, 1 ], 1.0); - * shape.addBox([ 0, 3, 0 ], [ 1, 0, 1 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]); - * var shapeComp = stage.addComponentFromObject(shape); - * geoComp.addRepresentation('buffer'); - */ -class Shape { - name: string - parameters: ShapeParameters - - boundingBox = new Box2() - bufferList: Buffer[] = [] - meshCount = 0 - - _origin?: Vector2 - _primitiveData: { [k: string]: any } = {} - - /** - * @param {String} name - name - * @param {Object} params - parameter object - * @param {Integer} params.aspectRatio - arrow aspect ratio, used for cylinder radius and cone length - * @param {Integer} params.sphereDetail - sphere quality (icosahedron subdivisions) - * @param {Integer} params.radialSegments - cylinder quality (number of segments) - * @param {Boolean} params.disableImpostor - disable use of raycasted impostors for rendering - * @param {Boolean} params.openEnded - capped or not - * @param {TextBufferParameters} params.labelParams - label parameters - */ - constructor (name = 'shape', params: Partial = {}) { - this.name = name - - this.parameters = createParams(params, ShapeDefaultParameters) - - Primitives.forEach(P => { - Object.keys(P.fields).forEach(name => { - this._primitiveData[ P.getShapeKey(name) ] = [] - }) - this._primitiveData[ P.getShapeKey('name') ] = [] - }) - } - - /** - * Add a buffer - * @param {Buffer} buffer - buffer object - * @return {Shape} this object - */ - addBuffer (buffer: Buffer) { - this.bufferList.push(buffer) - - const geometry = (buffer as any).geometry // TODO - if (!geometry.boundingBox) { - geometry.computeBoundingBox() - } - this.boundingBox.union(geometry.boundingBox) - - return this - } - - /** - * Add a mesh - * @example - * shape.addMesh( - * [ 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1 ], - * [ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 ] - * ); - * - * @param {Float32Array|Array} position - positions - * @param {Float32Array|Array} color - colors - * @param {Uint32Array|Uint16Array|Array} [index] - indices - * @param {Float32Array|Array} [normal] - normals - * @param {String} [name] - text - * @return {Shape} this object - */ - addMesh (position: Float32Array|number[], color:Float32Array|number[], index: Uint32Array|Uint16Array|number[], normal: Float32Array|number[], name?: string) { - position = ensureFloat32Array(position) - color = ensureFloat32Array(color) - if (Array.isArray(index)) { - index = getUintArray(index, position.length) - } - if (normal) { - normal = ensureFloat32Array(normal) - } - - const data = { position, color, index, normal } - - - tmpBox.setFromArray(position) - this.boundingBox.union(tmpBox) - this.meshCount += 1 - - return this - } - - /** - * Add a sphere - * @example - * shape.addSphere([ 0, 0, 9 ], [ 1, 0, 0 ], 1.5); - * - * @param {Vector3|Array} position - position vector or array - * @param {Color|Array} color - color object or array - * @param {Float} radius - radius value - * @param {String} [name] - text - * @return {Shape} this object - */ - addSphere (position: Vector3|[number, number, number], color: Color|[number, number, number], radius: number, name: string) { - SpherePrimitive.objectToShape( - this, { position, color, radius, name } - ) - return this - } - - - - /** - * Add a box - * @example - * shape.addBox([ 0, 3, 0 ], [ 1, 0, 1 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]); - * - * @param {Vector3|Array} position - position vector or array - * @param {Color|Array} color - color object or array - * @param {Float} size - size value - * @param {Vector3|Array} heightAxis - height axis vector or array - * @param {Vector3|Array} depthAxis - depth axis vector or array - * @param {String} [name] - text - * @return {Shape} this object - */ - addBox (position: Vector3|[number, number, number], color: Color|[number, number, number], size: number, heightAxis: Vector3|[number, number, number], depthAxis: Vector3|[number, number, number], name: string) { - BoxPrimitive.objectToShape( - this, { position, color, size, heightAxis, depthAxis, name } - ) - return this - } - - - /** - * Add point - * @example - * shape.addPoint([ 10, -2, 4 ], [ 0.2, 0.5, 0.8 ]); - * - * @param {Vector3|Array} position - position vector or array - * @param {Color|Array} color - color object or array - * @param {String} [name] - text - * @return {Shape} this object - */ - addPoint (position: Vector3|[number, number, number], color: Color|[number, number, number], name: string) { - PointPrimitive.objectToShape( - this, { position, color, name } - ) - return this - } - - - - getBufferList () { - const buffers: Buffer[] = [] - - Primitives.forEach(P => { - if (this._primitiveData[ P.getShapeKey('color') ].length) { - buffers.push(P.bufferFromShape(this, this.parameters)) - } - }) - - return this.bufferList.concat(buffers) - } - - dispose () { - this.bufferList.forEach(function (buffer) { - buffer.dispose() - }) - this.bufferList.length = 0 - - Primitives.forEach(P => { - Object.keys(P.fields).forEach(name => { - this._primitiveData[ P.getShapeKey(name) ].length = 0 - }) - this._primitiveData[ P.getShapeKey('name') ].length = 0 - }) - } - - get origin () { - if (!this._origin) { - this._origin = this.boundingBox.getOrigin(new Vector2()) - } - return this._origin - } - - get type () { return 'Shape' } -} - -export default Shape diff --git a/src/stage/selecting-behavior.ts b/src/stage/selecting-behavior.ts index 3a60a38e9..27f3d0344 100644 --- a/src/stage/selecting-behavior.ts +++ b/src/stage/selecting-behavior.ts @@ -20,7 +20,7 @@ class PickingBehavior { this.controls = stage.mouseControls this.mouse.signals.clicked.add(this._onClick, this) - this.mouse.signals.dragged.add(this._onDragXY, this) + this.mouse.signals.draggedXY.add(this._onDragXY, this) this.mouse.signals.doubleClicked.add(this._onDoubleClick, this) } @@ -31,19 +31,21 @@ class PickingBehavior { } _onDragXY (x0: number, y0: number, x1: number, y1: number) { - const pickedProxies = this.stage.pickingControls.pickAll(x0, y0, x1-x0, y1-y0) - this.controls.run('select') - - + const sp = this.stage.getParameters() as any + if (sp.dragSelection) { + const pickedProxies = this.stage.pickingControls.pickAll(x0, y0, x1-x0, y1-y0) + this.controls.run('drag', pickedProxies, x1, y1) + } } - _onMouseDown (x: number, y: number) { - + _onDoubleClick (x: number, y: number) { + this.controls.run('doubleClick') } dispose () { this.mouse.signals.clicked.remove(this._onClick, this) - this.mouse.signals.hovered.remove(this._onHover, this) + this.mouse.signals.draggedXY.remove(this._onDragXY, this) + this.mouse.signals.doubleClicked.remove(this._onDoubleClick, this) } } diff --git a/src/stage/stage.ts b/src/stage/stage.ts index edafb4109..c0c4a4f3f 100644 --- a/src/stage/stage.ts +++ b/src/stage/stage.ts @@ -15,6 +15,7 @@ import { degToRad, clamp, pclamp } from '../math/math-utils' import Counter from '../utils/counter' import Viewer from '../viewer/viewer' import { ImageParameters } from '../viewer/viewer-utils' +import DragSelection from '../viewer/drag-selection' import MouseObserver from './mouse-observer' import TrackballControls from '../controls/trackball-controls' @@ -138,6 +139,7 @@ export const StageDefaultParameters = { ambientIntensity: 0.2, hoverTimeout: 0, tooltip: true, + dragSelection: true, mousePreset: 'default' as MouseControlPreset } export type StageParameters = typeof StageDefaultParameters @@ -177,6 +179,7 @@ class Stage { viewer: Viewer tooltip: HTMLElement + dragSelection: DragSelection lastFullscreenElement: HTMLElement mouseObserver: MouseObserver @@ -212,6 +215,8 @@ class Stage { }) this.viewer.container.appendChild(this.tooltip) + this.dragSelection = new DragSelection(this.viewer) + this.mouseObserver = new MouseObserver(this.viewer.renderer.domElement) this.viewerControls = new ViewerControls(this) this.trackballControls = new TrackballControls(this) @@ -903,6 +908,17 @@ class Stage { this.eachComponent((sc: StructureComponent) => sc.selectedUpdate(), 'structure') } + get selectedProxies () { + let proxies: AtomProxy[] = []; + this.eachComponent(function (sc: StructureComponent) { + sc.selectedAtomIndices.list.forEach(function (i) { + let ap = sc.structure.getAtomProxy(i) + proxies.push(ap) + }) + }, "structure") + return proxies + } + /** * Cleanup when disposing of a stage object diff --git a/src/utils/toggle-set.ts b/src/utils/toggle-set.ts index 0d860ca1c..17181caf6 100644 --- a/src/utils/toggle-set.ts +++ b/src/utils/toggle-set.ts @@ -1,7 +1,5 @@ -import value from "*.frag"; - /** - * @file Queue + * @file toggle-set * @author Lily Wang * @private */ diff --git a/src/viewer/drag-selection.ts b/src/viewer/drag-selection.ts new file mode 100644 index 000000000..70bcefae4 --- /dev/null +++ b/src/viewer/drag-selection.ts @@ -0,0 +1,75 @@ +/** + * @file Selection-Box + * @author Lily Wang + * @private + */ + +import Viewer from './viewer' + +export default class DragSelection { + + viewer: Viewer + element: HTMLElement + + startPoint: {x: number, y: number}; + pointTopLeft: {x: number, y: number}; + pointBottomRight: {x: number, y: number}; + + isDown: Boolean; + + + constructor (viewer: Viewer) { + + this.viewer = viewer; + + this.element = document.createElement('div'); + + Object.assign(this.element.style, { + display: 'none', + position: 'fixed', + zIndex: '1000000', + pointerEvents: 'none', + border: '1px solid #55aaff', + backgroundColor: 'rgba(75, 160, 255, 0.3)', + }) + this.viewer.container.appendChild(this.element) + + this.startPoint = { x: 0, y: 0 }; + this.pointTopLeft = { x: 0, y: 0 }; + this.pointBottomRight = { x: 0, y: 0 }; + + this.isDown = false; + } + + createSelection (x: number, y: number) { + this.element.style.display = 'block'; + this.element.style.left = x + 'px'; + this.element.style.top = y + 'px'; + this.element.style.width = '0px'; + this.element.style.height = '0px'; + + this.startPoint.x = x; + this.startPoint.y = y; + } + + moveSelection (x: number, y: number) { + if (!this.isDown) return; + + this.pointBottomRight.x = Math.max( this.startPoint.x, x ); + this.pointBottomRight.y = Math.max( this.startPoint.y, y ); + this.pointTopLeft.x = Math.min( this.startPoint.x, x ); + this.pointTopLeft.y = Math.min( this.startPoint.y, y ); + + this.element.style.left = this.pointTopLeft.x + 'px'; + this.element.style.top = this.pointTopLeft.y + 'px'; + this.element.style.width = ( this.pointBottomRight.x - this.pointTopLeft.x ) + 'px'; + this.element.style.height = ( this.pointBottomRight.y - this.pointTopLeft.y ) + 'px'; + } + + removeSelection () { + this.element.style.display = 'none'; + this.isDown = false; + } + + +} \ No newline at end of file From 597b1435ea7bbc2c5332e05babd91c34dcf183c7 Mon Sep 17 00:00:00 2001 From: Lily Wang Date: Mon, 6 May 2019 23:54:41 +1000 Subject: [PATCH 03/16] builds --- src/controls/mouse-actions.ts | 104 ++++++++++++++++----------------- src/controls/mouse-controls.ts | 1 + src/ui/parameters.ts | 1 + 3 files changed, 54 insertions(+), 52 deletions(-) diff --git a/src/controls/mouse-actions.ts b/src/controls/mouse-actions.ts index 256de7559..b213f2bcb 100644 --- a/src/controls/mouse-actions.ts +++ b/src/controls/mouse-actions.ts @@ -305,57 +305,57 @@ class MouseActions { type MouseActionPreset = [ string, MouseActionCallback ][] export const MouseActionPresets = { default: [ - [ 'scroll', MouseActions.zoomScroll ], - [ 'scroll-shift', MouseActions.focusScroll ], - [ 'scroll-ctrl', MouseActions.isolevelScroll ], - [ 'scroll-shift-ctrl', MouseActions.zoomFocusScroll ], - - [ 'drag-left', MouseActions.rotateDrag ], - [ 'drag-right', MouseActions.panDrag ], - [ 'drag-ctrl-left', MouseActions.panDrag ], - [ 'drag-ctrl-right', MouseActions.zRotateDrag ], - [ 'drag-shift-left', MouseActions.zoomDrag ], - [ 'drag-middle', MouseActions.zoomFocusDrag ], - - [ 'drag-ctrl-shift-right', MouseActions.panComponentDrag ], - [ 'drag-ctrl-shift-left', MouseActions.rotateComponentDrag ], - - [ 'clickPick-right', MouseActions.measurePick ], - [ 'clickPick-ctrl-left', MouseActions.measurePick ], - [ 'clickPick-middle', MouseActions.movePick ], - [ 'clickPick-left', MouseActions.movePick ], - [ 'hoverPick', MouseActions.tooltipPick ] - ] as MouseActionPreset, - pymol: [ - [ 'drag-left', MouseActions.rotateDrag ], - [ 'drag-middle', MouseActions.panDrag ], - [ 'drag-right', MouseActions.zoomDrag ], - [ 'drag-shift-right', MouseActions.focusScroll ], - - [ 'clickPick-ctrl+shift-middle', MouseActions.movePick ], - [ 'hoverPick', MouseActions.tooltipPick ] - ] as MouseActionPreset, - coot: [ - [ 'scroll', MouseActions.isolevelScroll ], - - [ 'drag-left', MouseActions.rotateDrag ], - [ 'drag-middle', MouseActions.panDrag ], - [ 'drag-ctrl-left', MouseActions.panDrag ], - [ 'drag-right', MouseActions.zoomFocusDrag ], - [ 'drag-ctrl-right', MouseActions.focusScroll ], - - [ 'clickPick-middle', MouseActions.movePick ], - [ 'hoverPick', MouseActions.tooltipPick ] - ] as MouseActionPreset, - astexviewer: [ - [ 'drag-left', MouseActions.rotateDrag ], - [ 'drag-ctrl-left', MouseActions.panDrag ], - [ 'drag-shift-left', MouseActions.zoomDrag ], - [ 'scroll', MouseActions.focusScroll ], - [ 'clickPick-middle', MouseActions.movePick ], - [ 'hoverPick', MouseActions.tooltipPick ] - ] as MouseActionPreset, - iqmol: [ + // [ 'scroll', MouseActions.zoomScroll ], + // [ 'scroll-shift', MouseActions.focusScroll ], + // [ 'scroll-ctrl', MouseActions.isolevelScroll ], + // [ 'scroll-shift-ctrl', MouseActions.zoomFocusScroll ], + + // [ 'drag-left', MouseActions.rotateDrag ], + // [ 'drag-right', MouseActions.panDrag ], + // [ 'drag-ctrl-left', MouseActions.panDrag ], + // [ 'drag-ctrl-right', MouseActions.zRotateDrag ], + // [ 'drag-shift-left', MouseActions.zoomDrag ], + // [ 'drag-middle', MouseActions.zoomFocusDrag ], + + // [ 'drag-ctrl-shift-right', MouseActions.panComponentDrag ], + // [ 'drag-ctrl-shift-left', MouseActions.rotateComponentDrag ], + + // [ 'clickPick-right', MouseActions.measurePick ], + // [ 'clickPick-ctrl-left', MouseActions.measurePick ], + // [ 'clickPick-middle', MouseActions.movePick ], + // [ 'clickPick-left', MouseActions.movePick ], + // [ 'hoverPick', MouseActions.tooltipPick ] + // ] as MouseActionPreset, + // pymol: [ + // [ 'drag-left', MouseActions.rotateDrag ], + // [ 'drag-middle', MouseActions.panDrag ], + // [ 'drag-right', MouseActions.zoomDrag ], + // [ 'drag-shift-right', MouseActions.focusScroll ], + + // [ 'clickPick-ctrl+shift-middle', MouseActions.movePick ], + // [ 'hoverPick', MouseActions.tooltipPick ] + // ] as MouseActionPreset, + // coot: [ + // [ 'scroll', MouseActions.isolevelScroll ], + + // [ 'drag-left', MouseActions.rotateDrag ], + // [ 'drag-middle', MouseActions.panDrag ], + // [ 'drag-ctrl-left', MouseActions.panDrag ], + // [ 'drag-right', MouseActions.zoomFocusDrag ], + // [ 'drag-ctrl-right', MouseActions.focusScroll ], + + // [ 'clickPick-middle', MouseActions.movePick ], + // [ 'hoverPick', MouseActions.tooltipPick ] + // ] as MouseActionPreset, + // astexviewer: [ + // [ 'drag-left', MouseActions.rotateDrag ], + // [ 'drag-ctrl-left', MouseActions.panDrag ], + // [ 'drag-shift-left', MouseActions.zoomDrag ], + // [ 'scroll', MouseActions.focusScroll ], + // [ 'clickPick-middle', MouseActions.movePick ], + // [ 'hoverPick', MouseActions.tooltipPick ] + // ] as MouseActionPreset, + // iqmol: [ [ 'scroll', MouseActions.zoomScroll ], // [ 'scroll-shift', MouseActions.focusScroll ], // [ 'scroll-ctrl', MouseActions.isolevelScroll ], @@ -374,7 +374,7 @@ export const MouseActionPresets = { [ 'clickPick-right', MouseActions.measurePick ], [ 'clickPick-middle', MouseActions.movePick ], [ 'hoverPick', MouseActions.tooltipPick ] - ] + ] as MouseActionPreset } export default MouseActions diff --git a/src/controls/mouse-controls.ts b/src/controls/mouse-controls.ts index 7340bb838..80e39e387 100644 --- a/src/controls/mouse-controls.ts +++ b/src/controls/mouse-controls.ts @@ -62,6 +62,7 @@ function triggerFromString (str: string) { let type = '' if (tokens.includes('scroll')) type = 'scroll' if (tokens.includes('drag')) type = 'drag' + if (tokens.includes('drag')) type = 'drag' if (tokens.includes('click')) type = 'click' if (tokens.includes('doubleClick')) type = 'doubleClick' if (tokens.includes('hover')) type = 'hover' diff --git a/src/ui/parameters.ts b/src/ui/parameters.ts index 813539978..703a7e19b 100644 --- a/src/ui/parameters.ts +++ b/src/ui/parameters.ts @@ -57,5 +57,6 @@ export const UIStageParameters: { [k in keyof StageParameters]: ParamType } = { ambientIntensity: NumberParam(2, 10, 0), hoverTimeout: IntegerParam(10000, -1), tooltip: BooleanParam(), + dragSelection: BooleanParam(), mousePreset: SelectParam(...Object.keys(MouseActionPresets)) } From 3c73779dd7128effa58cd5755311ef52d7419fd1 Mon Sep 17 00:00:00 2001 From: Lily Wang Date: Tue, 7 May 2019 00:49:43 +1000 Subject: [PATCH 04/16] bug fixing --- src/component/structure-component.ts | 13 ++++++++++--- src/controls/mouse-actions.ts | 2 +- src/controls/mouse-controls.ts | 4 ++-- src/controls/picking-controls.ts | 3 ++- src/stage/selecting-behavior.ts | 4 ++-- src/utils/toggle-set.ts | 24 +++++++++++++++++++++--- src/viewer/viewer.ts | 15 --------------- 7 files changed, 38 insertions(+), 27 deletions(-) diff --git a/src/component/structure-component.ts b/src/component/structure-component.ts index 6e5058af2..65a5ea718 100644 --- a/src/component/structure-component.ts +++ b/src/component/structure-component.ts @@ -93,6 +93,7 @@ class StructureComponent extends Component { this.pickBuffer = createRingBuffer(4) this.pickDict = createSimpleDict() this.selectedAtomIndices = createToggleSet() + console.log('THIS IS', this.selectedAtomIndices) this.spacefillRepresentation = this.addRepresentation('spacefill', { sele: 'none', @@ -111,9 +112,15 @@ class StructureComponent extends Component { this.dihedralRepresentation = this.addRepresentation( 'dihedral', MeasurementDefaultParams, true ) - this.selectedRepresentation = this.addRepresentation( - 'selected', MeasurementDefaultParams, true - ) + + this.selectedRepresentation = this.addRepresentation('spacefill', { + sele: 'none', + color: MeasurementDefaultParams.color, + opacity: 0.4, + disablePicking: true, + radiusType: 'data' + }, true) + this.measureRepresentations = new RepresentationCollection([ this.spacefillRepresentation, diff --git a/src/controls/mouse-actions.ts b/src/controls/mouse-actions.ts index b213f2bcb..ff7f9dc27 100644 --- a/src/controls/mouse-actions.ts +++ b/src/controls/mouse-actions.ts @@ -365,7 +365,7 @@ export const MouseActionPresets = { [ 'drag-right', MouseActions.panDrag ], [ 'drag-ctrl-left', MouseActions.rotateComponentDrag ], [ 'drag-ctrl-right', MouseActions.moveComponentDrag ], - [ 'drag-shift-left', MouseActions.selectPickAll ], + [ 'dragXY-shift-left', MouseActions.selectPickAll ], [ 'drag-middle', MouseActions.zoomFocusDrag ], [ 'clickPick-shift-left', MouseActions.selectPick ], diff --git a/src/controls/mouse-controls.ts b/src/controls/mouse-controls.ts index 80e39e387..9506dab0c 100644 --- a/src/controls/mouse-controls.ts +++ b/src/controls/mouse-controls.ts @@ -14,7 +14,7 @@ export interface MouseControlsParams { disabled?: boolean } -export type MouseActionType = ''|'scroll'|'drag'|'click'|'doubleClick'|'hover'|'clickPick'|'hoverPick' +export type MouseActionType = ''|'scroll'|'drag'|'click'|'doubleClick'|'hover'|'clickPick'|'hoverPick'|'dragXY' export interface MouseAction { type: MouseActionType key: number @@ -62,7 +62,7 @@ function triggerFromString (str: string) { let type = '' if (tokens.includes('scroll')) type = 'scroll' if (tokens.includes('drag')) type = 'drag' - if (tokens.includes('drag')) type = 'drag' + if (tokens.includes('dragXY')) type = 'dragXY' if (tokens.includes('click')) type = 'click' if (tokens.includes('doubleClick')) type = 'doubleClick' if (tokens.includes('hover')) type = 'hover' diff --git a/src/controls/picking-controls.ts b/src/controls/picking-controls.ts index 32c90dabe..bbccb6f6d 100644 --- a/src/controls/picking-controls.ts +++ b/src/controls/picking-controls.ts @@ -42,7 +42,8 @@ class PickingControls { pickAll (x0: number, y0: number, dx: number, dy: number) { const pickedData = this.viewer.pickAll(x0, y0, dx, dy) - let picked = [] + console.log('PICKED DATA IS', pickedData) + let picked: PickingProxy[] = [] for (var i = 0; i < pickedData.length; i++) { let pickingData = pickedData[i] diff --git a/src/stage/selecting-behavior.ts b/src/stage/selecting-behavior.ts index 27f3d0344..888f3b089 100644 --- a/src/stage/selecting-behavior.ts +++ b/src/stage/selecting-behavior.ts @@ -33,8 +33,8 @@ class PickingBehavior { _onDragXY (x0: number, y0: number, x1: number, y1: number) { const sp = this.stage.getParameters() as any if (sp.dragSelection) { - const pickedProxies = this.stage.pickingControls.pickAll(x0, y0, x1-x0, y1-y0) - this.controls.run('drag', pickedProxies, x1, y1) + let pickedProxies = this.stage.pickingControls.pickAll(x0, y0, x1-x0, y1-y0) + this.controls.run('dragXY', pickedProxies, x1, y1) } } diff --git a/src/utils/toggle-set.ts b/src/utils/toggle-set.ts index 17181caf6..3cabc94af 100644 --- a/src/utils/toggle-set.ts +++ b/src/utils/toggle-set.ts @@ -20,8 +20,16 @@ export function createToggleSet (): ToggleSet { return { has: function (value: T) { return list.indexOf(value) !== -1 }, - add: function (value: T) { if (!this.has(value)) list.push(value); }, - del: function (value: T) { if (this.has(value)) list.splice(list.indexOf(value), 1); }, + add: function (value: T) { + if (list.indexOf(value) === -1) { + list.push(value) + } + }, + del: function (value: T) { + if (list.indexOf(value) !== -1) { + list.splice(list.indexOf(value), 1) + } + }, toggle: function (value: T) { if (this.has(value)) { this.del(value) @@ -35,7 +43,17 @@ export function createToggleSet (): ToggleSet { if (!this.has(values[i])) addAll = true; } - if (addAll) values.forEach(this.add); else values.forEach(this.del) + let action + if (addAll) { + action = this.add + } else { + action = this.del + } + + for (var i = 0; i < values.length; i++) { + console.log('THIS ISSSS', this, action, i, values[i]) + action(values[i]) + } }, get count () { return list.length }, get list () {return list}, diff --git a/src/viewer/viewer.ts b/src/viewer/viewer.ts index 6f65629e4..f7062d85b 100644 --- a/src/viewer/viewer.ts +++ b/src/viewer/viewer.ts @@ -1050,21 +1050,6 @@ export default class Viewer { picked.push({ pid, instance, picker }) } - // if( Debug ){ - // const rgba = Array.apply( [], pixelBuffer ); - // Log.log( pixelBuffer ); - // Log.log( - // "picked color", - // rgba.map( c => { return c.toPrecision( 2 ) } ) - // ); - // Log.log( "picked pid", pid ); - // Log.log( "picked oid", oid ); - // Log.log( "picked object", object ); - // Log.log( "picked instance", instance ); - // Log.log( "picked position", x, y ); - // Log.log( "devicePixelRatio", window.devicePixelRatio ); - // } - return picked } From 2dd7c45aa4caa422c13a92d21f72733d4d91cdc8 Mon Sep 17 00:00:00 2001 From: Lily Wang Date: Tue, 7 May 2019 19:20:52 +1000 Subject: [PATCH 05/16] bug fixing --- doc/usage/interaction-controls.md | 18 ++++++++++ src/component/structure-component.ts | 16 +++++---- src/controls/mouse-actions.ts | 18 +++++++--- src/controls/mouse-controls.ts | 4 ++- src/controls/trackball-controls.ts | 52 +++++++++++++++++++++++++--- src/globals.ts | 15 ++++++++ src/ngl.ts | 1 + src/stage/mouse-observer.ts | 6 +++- src/stage/selecting-behavior.ts | 42 ++++++++++++++-------- src/stage/stage.ts | 11 ++++++ src/utils/toggle-set.ts | 1 - src/viewer/drag-selection.ts | 5 +++ 12 files changed, 156 insertions(+), 33 deletions(-) diff --git a/doc/usage/interaction-controls.md b/doc/usage/interaction-controls.md index 12551a609..8d15af121 100644 --- a/doc/usage/interaction-controls.md +++ b/doc/usage/interaction-controls.md @@ -152,6 +152,24 @@ The default controls are as follows: - `clickPick-middle` auto view picked component element - `hoverPick` show tooltip for hovered component element +Four presets are available: "default", "coot", "astexviewer", and "iqmol". The iqmol preset allows you to select atoms and drag them to edit their positions. + +The iqmol controls are as follows: + +- `scroll` zoom scene +- `scroll-ctrl` move near clipping plane +- `scroll-shift` move near clipping plane and far fog +- `scroll-alt` change isolevel of isosurfaces +- `drag-right` pan/translate scene +- `drag-left` rotate scene +- `drag-middle` zoom scene +- `drag-shift-left` select atoms via lasso +- `drag-ctrl-right` drag selected atoms +- `drag-ctrl-left` rotate selected atoms +- `doubleClick-shift-left` clear selected atoms +- `clickPick-middle` auto view picked component element +- `hoverPick` show tooltip for hovered component element + ### Observer diff --git a/src/component/structure-component.ts b/src/component/structure-component.ts index 65a5ea718..52761047f 100644 --- a/src/component/structure-component.ts +++ b/src/component/structure-component.ts @@ -6,7 +6,7 @@ import { Signal } from 'signals' -import { ComponentRegistry, MeasurementDefaultParams } from '../globals' +import { ComponentRegistry, MeasurementDefaultParams, SelectionDefaultParams } from '../globals' import { defaults, /*deepEqual, */createRingBuffer, RingBuffer, createSimpleDict, SimpleDict } from '../utils' @@ -30,7 +30,7 @@ import { createToggleSet, ToggleSet } from '../utils/toggle-set'; export type StructureRepresentationType = ( 'angle'|'axes'|'backbone'|'ball+stick'|'base'|'cartoon'|'contact'|'dihedral'| 'distance'|'helixorient'|'hyperball'|'label'|'licorice'|'line'|'surface'| - 'ribbon'|'rocket'|'rope'|'selected'|'spacefill'|'trace'|'tube'|'unitcell' + 'ribbon'|'rocket'|'rope'|'selected'|'spacefill'|'trace'|'tube'|'unitcell'|'selected' ) export const StructureComponentDefaultParameters = Object.assign({ @@ -93,7 +93,6 @@ class StructureComponent extends Component { this.pickBuffer = createRingBuffer(4) this.pickDict = createSimpleDict() this.selectedAtomIndices = createToggleSet() - console.log('THIS IS', this.selectedAtomIndices) this.spacefillRepresentation = this.addRepresentation('spacefill', { sele: 'none', @@ -115,7 +114,7 @@ class StructureComponent extends Component { this.selectedRepresentation = this.addRepresentation('spacefill', { sele: 'none', - color: MeasurementDefaultParams.color, + color: SelectionDefaultParams.color, opacity: 0.4, disablePicking: true, radiusType: 'data' @@ -451,7 +450,10 @@ class StructureComponent extends Component { } selectedPick (atoms: AtomProxy[]) { - var atomIndices = atoms.map(x => x.index) + let atomIndices: number[] = [] + atoms.forEach(function (x) { + atomIndices.push(x.index) + }) this.selectedAtomIndices.toggleAny(atomIndices) this.selectedUpdate() } @@ -463,10 +465,10 @@ class StructureComponent extends Component { const r = Math.max(0.1, this.getMaxRepresentationRadius(ai)) radiusData[ ai ] = r * (2.3 - smoothstep(0.1, 2, r)) }) - this.spacefillRepresentation.setSelection( + this.selectedRepresentation.setSelection( pickData.length ? ( '@' + pickData.join(',') ) : 'none' ) - this.spacefillRepresentation.setParameters({ radiusData }) + this.selectedRepresentation.setParameters({ radiusData }) } } diff --git a/src/controls/mouse-actions.ts b/src/controls/mouse-actions.ts index ff7f9dc27..acd73bff2 100644 --- a/src/controls/mouse-actions.ts +++ b/src/controls/mouse-actions.ts @@ -188,6 +188,10 @@ class MouseActions { stage.trackballControls.translateAtoms(dx, dy) } + static rotateSelectionDrag (stage: Stage, dx: number, dy: number) { + stage.trackballControls.rotateAtoms(dx, dy) + } + /** * Move picked element to the center of the screen * @param {Stage} stage - the stage @@ -278,16 +282,19 @@ class MouseActions { static clearSelect (stage: Stage) { stage.eachComponent(function (sc: StructureComponent) { sc.selectedAtomIndices.clear() + sc.selectedUpdate() }, "structure") } static onSelectDown (stage: Stage, x: number, y: number) { + console.log('ON SELECT DOWN') const ds = stage.dragSelection const sp = stage.getParameters() as any if (sp.dragSelection) { ds.createSelection(x, y) } else { ds.removeSelection() + console.log('rem??') } } @@ -357,13 +364,16 @@ export const MouseActionPresets = { // ] as MouseActionPreset, // iqmol: [ [ 'scroll', MouseActions.zoomScroll ], - // [ 'scroll-shift', MouseActions.focusScroll ], - // [ 'scroll-ctrl', MouseActions.isolevelScroll ], - // [ 'scroll-shift-ctrl', MouseActions.zoomFocusScroll ], + [ 'scroll-shift', MouseActions.focusScroll ], + [ 'scroll-ctrl', MouseActions.isolevelScroll ], + [ 'scroll-shift-ctrl', MouseActions.zoomFocusScroll ], + + [ 'press-shift-left', MouseActions.onSelectDown], + [ 'drop-shift-left', MouseActions.onSelectUp], [ 'drag-left', MouseActions.rotateDrag ], [ 'drag-right', MouseActions.panDrag ], - [ 'drag-ctrl-left', MouseActions.rotateComponentDrag ], + [ 'drag-ctrl-left', MouseActions.rotateSelectionDrag ], [ 'drag-ctrl-right', MouseActions.moveComponentDrag ], [ 'dragXY-shift-left', MouseActions.selectPickAll ], [ 'drag-middle', MouseActions.zoomFocusDrag ], diff --git a/src/controls/mouse-controls.ts b/src/controls/mouse-controls.ts index 9506dab0c..8a077b45f 100644 --- a/src/controls/mouse-controls.ts +++ b/src/controls/mouse-controls.ts @@ -14,7 +14,7 @@ export interface MouseControlsParams { disabled?: boolean } -export type MouseActionType = ''|'scroll'|'drag'|'click'|'doubleClick'|'hover'|'clickPick'|'hoverPick'|'dragXY' +export type MouseActionType = ''|'scroll'|'drag'|'click'|'doubleClick'|'hover'|'clickPick'|'hoverPick'|'dragXY'|'press'|'drop' export interface MouseAction { type: MouseActionType key: number @@ -68,6 +68,8 @@ function triggerFromString (str: string) { if (tokens.includes('hover')) type = 'hover' if (tokens.includes('clickPick')) type = 'clickPick' if (tokens.includes('hoverPick')) type = 'hoverPick' + if (tokens.includes('press')) type = 'press' + if (tokens.includes('drop')) type = 'drop' let key = 0 if (tokens.includes('alt')) key += 1 diff --git a/src/controls/trackball-controls.ts b/src/controls/trackball-controls.ts index bbe658460..2763a7744 100644 --- a/src/controls/trackball-controls.ts +++ b/src/controls/trackball-controls.ts @@ -152,10 +152,10 @@ class TrackballControls { } translateAtoms (x: number, y: number) { - let _move = this._translateComponent - this.stage.eachComponent(function (sc: StructureComponent) { - _move(sc, x, y) - }) + let comps = this.stage.structureComponents + for (var i = 0; i < comps.length; i++) { + this._translateComponent(comps[i], x, y) + } } rotate (x: number, y: number) { @@ -194,6 +194,50 @@ class TrackballControls { this.component.updateMatrix() } + _rotateAtoms (comp: StructureComponent, x: number, y: number) { + // TODO + // Fix rotation + const [ dx, dy ] = this._getRotateXY(x, y) + + let rot: Matrix4 = this.viewer.rotationGroup.matrix + let rotInv: Matrix4 = this.viewer.rotationGroup.matrix + rotInv.getInverse(rotInv) + + tmpRotateMatrix.extractRotation(comp.transform) + tmpRotateMatrix.premultiply(rot) + tmpRotateMatrix.getInverse(tmpRotateMatrix) + tmpRotateVector.set(1, 0, 0) + tmpRotateVector.applyMatrix4(tmpRotateMatrix) + tmpRotateXMatrix.makeRotationAxis(tmpRotateVector, dy) + tmpRotateVector.set(0, 1, 0) + tmpRotateVector.applyMatrix4(tmpRotateMatrix) + tmpRotateYMatrix.makeRotationAxis(tmpRotateVector, dx) + tmpRotateXMatrix.multiply(tmpRotateYMatrix) + tmpRotateQuaternion.setFromRotationMatrix(tmpRotateXMatrix) + + for (var j = 0; j < comp.selectedAtomIndices.list.length; j++) { + let i = comp.selectedAtomIndices.list[j] + let atom = comp.structure.getAtomProxy(i) + let _tmpAtomVector = new Vector3(); + atom.positionToVector3(_tmpAtomVector) + + _tmpAtomVector.add(this.viewer.translationGroup.position) + _tmpAtomVector.applyMatrix4(rot) + _tmpAtomVector.applyQuaternion(tmpRotateQuaternion) + _tmpAtomVector.applyMatrix4(rotInv) + _tmpAtomVector.sub(this.viewer.translationGroup.position) + atom.positionFromVector3(_tmpAtomVector) + } + + comp.updateRepresentations({'position': true}) + } + + rotateAtoms (x: number, y: number) { + let comps = this.stage.structureComponents + for (var i = 0; i < comps.length; i++) { + this._rotateAtoms(comps[i], x, y) + } + } } export default TrackballControls diff --git a/src/globals.ts b/src/globals.ts index a31a62cc9..69b94d11f 100644 --- a/src/globals.ts +++ b/src/globals.ts @@ -75,10 +75,25 @@ export let MeasurementDefaultParams = { arcVisible: true, planeVisible: false } + +export let SelectionDefaultParams = { + color: 'white', + lineOpacity: 0.8, + linewidth: 5.0, + opacity: 0.6, + + labelUnit: 'angstrom', + arcVisible: true, + planeVisible: false +} export function setMeasurementDefaultParams (params = {}) { Object.assign(MeasurementDefaultParams, params) } +export function setSelectionDefaultParams (params = {}) { + Object.assign(SelectionDefaultParams, params) +} + export let Debug = boolean(getQuery('debug')) export function setDebug (value: boolean) { Debug = value diff --git a/src/ngl.ts b/src/ngl.ts index 98a2e78be..e75b3a468 100644 --- a/src/ngl.ts +++ b/src/ngl.ts @@ -15,6 +15,7 @@ import _Promise from 'promise-polyfill' export { Debug, setDebug, MeasurementDefaultParams, setMeasurementDefaultParams, + SelectionDefaultParams, setSelectionDefaultParams, ScriptExtensions, ColormakerRegistry, DatasourceRegistry, DecompressorRegistry, ParserRegistry, RepresentationRegistry, diff --git a/src/stage/mouse-observer.ts b/src/stage/mouse-observer.ts index 3939e2960..3f32170cf 100644 --- a/src/stage/mouse-observer.ts +++ b/src/stage/mouse-observer.ts @@ -67,6 +67,7 @@ export interface MouseSignals { clicked: Signal // on click hovered: Signal // on hover doubleClicked: Signal + pressed: Signal } export interface MouseParams { @@ -111,7 +112,8 @@ class MouseObserver { dropped: new Signal(), clicked: new Signal(), hovered: new Signal(), - doubleClicked: new Signal() + doubleClicked: new Signal(), + pressed: new Signal(), } hoverTimeout: number @@ -304,6 +306,7 @@ class MouseObserver { this.buttons = getMouseButtons(event) this.pressed = true this._setCanvasPosition(event) + this.signals.pressed.dispatch(event.clientX, event.clientY) } /** @@ -326,6 +329,7 @@ class MouseObserver { this.doubleClickPending = false } this.signals.clicked.dispatch(cp.x, cp.y) + this.signals.dropped.dispatch(); this.doubleClickPending = true this.prevClickCP.copy(cp) } diff --git a/src/stage/selecting-behavior.ts b/src/stage/selecting-behavior.ts index 888f3b089..c38b9a9ff 100644 --- a/src/stage/selecting-behavior.ts +++ b/src/stage/selecting-behavior.ts @@ -9,7 +9,7 @@ import MouseObserver from './mouse-observer' import Viewer from '../viewer/viewer' import MouseControls from '../controls/mouse-controls' -class PickingBehavior { +class SelectingBehavior { viewer: Viewer mouse: MouseObserver controls: MouseControls @@ -19,34 +19,46 @@ class PickingBehavior { this.mouse = stage.mouseObserver this.controls = stage.mouseControls - this.mouse.signals.clicked.add(this._onClick, this) + // this.mouse.signals.clicked.add(this._onClick, this) + this.mouse.signals.pressed.add(this._onPress, this) this.mouse.signals.draggedXY.add(this._onDragXY, this) - this.mouse.signals.doubleClicked.add(this._onDoubleClick, this) + this.mouse.signals.dropped.add(this._onDrop, this) + // this.mouse.signals.doubleClicked.add(this._onDoubleClick, this) } - _onClick (x: number, y: number) { - const pickingProxy = this.stage.pickingControls.pick(x, y) - this.stage.signals.clicked.dispatch(pickingProxy) - this.controls.run('clickPick', pickingProxy) + // _onClick (x: number, y: number) { + // const pickingProxy = this.stage.pickingControls.pick(x, y) + // this.stage.signals.clicked.dispatch(pickingProxy) + // this.controls.run('clickPick', pickingProxy) + // } + + _onPress (x: number, y: number) { + this.controls.run('press', x, y) + } + + _onDrop () { + this.controls.run('drop') } _onDragXY (x0: number, y0: number, x1: number, y1: number) { - const sp = this.stage.getParameters() as any - if (sp.dragSelection) { + // const sp = this.stage.getParameters() as any + if (this.stage.dragSelection.isDown) { let pickedProxies = this.stage.pickingControls.pickAll(x0, y0, x1-x0, y1-y0) this.controls.run('dragXY', pickedProxies, x1, y1) } } - _onDoubleClick (x: number, y: number) { - this.controls.run('doubleClick') - } + // _onDoubleClick (x: number, y: number) { + // this.controls.run('doubleClick') + // } dispose () { - this.mouse.signals.clicked.remove(this._onClick, this) + // this.mouse.signals.clicked.remove(this._onClick, this) + this.mouse.signals.pressed.remove(this._onPress, this) this.mouse.signals.draggedXY.remove(this._onDragXY, this) - this.mouse.signals.doubleClicked.remove(this._onDoubleClick, this) + this.mouse.signals.dropped.remove(this._onDrop, this) + // this.mouse.signals.doubleClicked.remove(this._onDoubleClick, this) } } -export default PickingBehavior +export default SelectingBehavior diff --git a/src/stage/stage.ts b/src/stage/stage.ts index c0c4a4f3f..78a670c4c 100644 --- a/src/stage/stage.ts +++ b/src/stage/stage.ts @@ -26,6 +26,7 @@ import MouseControls, { MouseControlPreset } from '../controls/mouse-controls' import KeyControls from '../controls/key-controls' import PickingBehavior from './picking-behavior' +import SelectingBehavior from './selecting-behavior' import MouseBehavior from './mouse-behavior' import AnimationBehavior from './animation-behavior' import KeyBehavior from './key-behavior' @@ -191,6 +192,7 @@ class Stage { keyControls: KeyControls pickingBehavior: PickingBehavior + selectingBehavior: SelectingBehavior mouseBehavior: MouseBehavior animationBehavior: AnimationBehavior keyBehavior: KeyBehavior @@ -226,6 +228,7 @@ class Stage { this.keyControls = new KeyControls(this) this.pickingBehavior = new PickingBehavior(this) + this.selectingBehavior = new SelectingBehavior(this) this.mouseBehavior = new MouseBehavior(this) this.animationBehavior = new AnimationBehavior(this) this.keyBehavior = new KeyBehavior(this) @@ -919,6 +922,14 @@ class Stage { return proxies } + get structureComponents () { + let comps: StructureComponent[] = []; + this.eachComponent(function (sc: StructureComponent) { + comps.push(sc) + }, "structure") + return comps + } + /** * Cleanup when disposing of a stage object diff --git a/src/utils/toggle-set.ts b/src/utils/toggle-set.ts index 3cabc94af..d52b41deb 100644 --- a/src/utils/toggle-set.ts +++ b/src/utils/toggle-set.ts @@ -51,7 +51,6 @@ export function createToggleSet (): ToggleSet { } for (var i = 0; i < values.length; i++) { - console.log('THIS ISSSS', this, action, i, values[i]) action(values[i]) } }, diff --git a/src/viewer/drag-selection.ts b/src/viewer/drag-selection.ts index 70bcefae4..7c46f6ab2 100644 --- a/src/viewer/drag-selection.ts +++ b/src/viewer/drag-selection.ts @@ -42,6 +42,7 @@ export default class DragSelection { } createSelection (x: number, y: number) { + console.log('creatin gsel') this.element.style.display = 'block'; this.element.style.left = x + 'px'; this.element.style.top = y + 'px'; @@ -50,10 +51,13 @@ export default class DragSelection { this.startPoint.x = x; this.startPoint.y = y; + + this.isDown = true; } moveSelection (x: number, y: number) { if (!this.isDown) return; + console.log('mv seling') this.pointBottomRight.x = Math.max( this.startPoint.x, x ); this.pointBottomRight.y = Math.max( this.startPoint.y, y ); @@ -67,6 +71,7 @@ export default class DragSelection { } removeSelection () { + console.log('removed') this.element.style.display = 'none'; this.isDown = false; } From a8ccc7b76f6805b3fb261cfa5dd35064a2c3cb07 Mon Sep 17 00:00:00 2001 From: Lily Wang Date: Wed, 8 May 2019 11:46:21 +1000 Subject: [PATCH 06/16] drag --- src/component/structure-component.ts | 85 ++++++----- src/controls/mouse-actions.ts | 221 +++++++++++++-------------- src/controls/picking-controls.ts | 21 ++- src/stage/mouse-observer.ts | 92 ++++++----- src/stage/selecting-behavior.ts | 14 +- src/utils/toggle-set.ts | 40 +++-- src/viewer/drag-selection.ts | 47 +++--- src/viewer/viewer.ts | 168 ++++++++++---------- 8 files changed, 354 insertions(+), 334 deletions(-) diff --git a/src/component/structure-component.ts b/src/component/structure-component.ts index 52761047f..74781cea9 100644 --- a/src/component/structure-component.ts +++ b/src/component/structure-component.ts @@ -28,9 +28,9 @@ import { Vector3, Box3 } from 'three'; import { createToggleSet, ToggleSet } from '../utils/toggle-set'; export type StructureRepresentationType = ( - 'angle'|'axes'|'backbone'|'ball+stick'|'base'|'cartoon'|'contact'|'dihedral'| - 'distance'|'helixorient'|'hyperball'|'label'|'licorice'|'line'|'surface'| - 'ribbon'|'rocket'|'rope'|'selected'|'spacefill'|'trace'|'tube'|'unitcell'|'selected' + 'angle' | 'axes' | 'backbone' | 'ball+stick' | 'base' | 'cartoon' | 'contact' | 'dihedral' | + 'distance' | 'helixorient' | 'hyperball' | 'label' | 'licorice' | 'line' | 'surface' | + 'ribbon' | 'rocket' | 'rope' | 'selected' | 'spacefill' | 'trace' | 'tube' | 'unitcell' | 'selected' ) export const StructureComponentDefaultParameters = Object.assign({ @@ -58,7 +58,7 @@ export interface StructureComponentSignals extends ComponentSignals { class StructureComponent extends Component { readonly signals: StructureComponentSignals readonly parameters: StructureComponentParameters - get defaultParameters () { return StructureComponentDefaultParameters } + get defaultParameters() { return StructureComponentDefaultParameters } selection: Selection structureView: StructureView @@ -77,7 +77,7 @@ class StructureComponent extends Component { measureRepresentations: RepresentationCollection - constructor (stage: Stage, readonly structure: Structure, params: Partial = {}) { + constructor(stage: Stage, readonly structure: Structure, params: Partial = {}) { super(stage, structure, Object.assign({ name: structure.name }, params)) this.signals = Object.assign(this.signals, { @@ -137,7 +137,7 @@ class StructureComponent extends Component { * Component type * @type {String} */ - get type () { return 'structure' } + get type() { return 'structure' } /** * Initialize selection @@ -145,7 +145,7 @@ class StructureComponent extends Component { * @param {String} sele - selection string * @return {undefined} */ - initSelection (sele: string) { + initSelection(sele: string) { /** * Selection for {@link StructureComponent#structureView} * @private @@ -175,7 +175,7 @@ class StructureComponent extends Component { * @param {String} string - selection string * @return {StructureComponent} this object */ - setSelection (string: string) { + setSelection(string: string) { this.parameters.sele = string this.selection.setString(string) return this @@ -186,7 +186,7 @@ class StructureComponent extends Component { * @param {String} value - assembly name * @return {undefined} */ - setDefaultAssembly (value:string) { + setDefaultAssembly(value: string) { // filter out non-existing assemblies if (this.structure.biomolDict[value] === undefined) value = '' // only set default assembly when changed @@ -205,7 +205,7 @@ class StructureComponent extends Component { * Rebuild all representations * @return {undefined} */ - rebuildRepresentations () { + rebuildRepresentations() { this.reprList.forEach((repr: RepresentationElement) => { repr.build() }) @@ -217,19 +217,19 @@ class StructureComponent extends Component { * Rebuild all trajectories * @return {undefined} */ - rebuildTrajectories () { + rebuildTrajectories() { this.trajList.forEach(trajComp => { trajComp.trajectory.setStructure(this.structureView) }) } - updateRepresentations (what: any) { + updateRepresentations(what: any) { super.updateRepresentations(what) this.measureRepresentations.update(what) this.selectedRepresentation.update(what) } - addRepresentation (type: StructureRepresentationType, params: { [k: string]: any } = {}, hidden = false) { + addRepresentation(type: StructureRepresentationType, params: { [k: string]: any } = {}, hidden = false) { params.defaultAssembly = this.parameters.defaultAssembly const reprComp = this._addRepresentation(type, this.structureView, params, hidden) @@ -242,7 +242,7 @@ class StructureComponent extends Component { /** * Add a new trajectory component to the structure */ - addTrajectory (trajPath = '', params: { [k: string]: any } = {}) { + addTrajectory(trajPath = '', params: { [k: string]: any } = {}) { const traj = makeTrajectory(trajPath, this.structureView, params as TrajectoryParameters) traj.signals.frameChanged.add(() => { @@ -256,7 +256,7 @@ class StructureComponent extends Component { return trajComp } - removeTrajectory (traj: TrajectoryElement) { + removeTrajectory(traj: TrajectoryElement) { const idx = this.trajList.indexOf(traj) if (idx !== -1) { this.trajList.splice(idx, 1) @@ -267,7 +267,7 @@ class StructureComponent extends Component { this.signals.trajectoryRemoved.dispatch(traj) } - dispose () { + dispose() { // copy via .slice because side effects may change trajList this.trajList.slice().forEach(traj => traj.dispose()) @@ -285,8 +285,8 @@ class StructureComponent extends Component { * @param {Integer} [duration] - duration of the animation, defaults to 0 * @return {undefined} */ - autoView (duration?: number): any - autoView (sele?: string|number, duration?: number) { + autoView(duration?: number): any + autoView(sele?: string | number, duration?: number) { if (typeof sele === 'number') { duration = sele sele = '' @@ -299,7 +299,7 @@ class StructureComponent extends Component { ) } - getBoxUntransformed (sele: string): Box3 { + getBoxUntransformed(sele: string): Box3 { let bb if (sele) { @@ -311,7 +311,7 @@ class StructureComponent extends Component { return bb } - getCenterUntransformed (sele: string): Vector3 { + getCenterUntransformed(sele: string): Vector3 { if (sele && typeof sele === 'string') { return this.structure.atomCenter(new Selection(sele)) } else { @@ -319,7 +319,7 @@ class StructureComponent extends Component { } } - superpose (component: StructureComponent, align: boolean, sele1: string, sele2: string) { + superpose(component: StructureComponent, align: boolean, sele1: string, sele2: string) { superpose( this.structureView, component.structureView, align, sele1, sele2 ) @@ -329,7 +329,7 @@ class StructureComponent extends Component { return this } - getMaxRepresentationRadius (atomIndex: number) { + getMaxRepresentationRadius(atomIndex: number) { let maxRadius = 0 const atom = this.structure.getAtomProxy(atomIndex) this.eachRepresentation(reprElem => { @@ -341,7 +341,7 @@ class StructureComponent extends Component { return maxRadius } - measurePick (atom: AtomProxy) { + measurePick(atom: AtomProxy) { const pickCount = this.pickBuffer.count if (this.lastPick === atom.index && pickCount >= 1) { @@ -379,33 +379,33 @@ class StructureComponent extends Component { this.measureUpdate() } - measureClear () { + measureClear() { this.pickBuffer.clear() this.lastPick = undefined this.spacefillRepresentation.setSelection('none') } - measureBuild () { + measureBuild() { const md = this.measureData() this.distanceRepresentation.setParameters({ atomPair: md.distance }) this.angleRepresentation.setParameters({ atomTriple: md.angle }) this.dihedralRepresentation.setParameters({ atomQuad: md.dihedral }) } - measureUpdate () { + measureUpdate() { const pickData = this.pickBuffer.data const radiusData: { [k: number]: number } = {} pickData.forEach(ai => { const r = Math.max(0.1, this.getMaxRepresentationRadius(ai)) - radiusData[ ai ] = r * (2.3 - smoothstep(0.1, 2, r)) + radiusData[ai] = r * (2.3 - smoothstep(0.1, 2, r)) }) this.spacefillRepresentation.setSelection( - pickData.length ? ( '@' + pickData.join(',') ) : 'none' + pickData.length ? ('@' + pickData.join(',')) : 'none' ) this.spacefillRepresentation.setParameters({ radiusData }) } - measureData () { + measureData() { const pv = this.pickDict.values return { distance: pv.filter(l => l.length === 2), @@ -417,7 +417,7 @@ class StructureComponent extends Component { /** * Remove all measurements, optionally limit to distance, angle or dihedral */ - removeAllMeasurements (type?: MeasurementFlags) { + removeAllMeasurements(type?: MeasurementFlags) { const pd = this.pickDict const pv = pd.values const remove = function (len: number) { @@ -432,7 +432,7 @@ class StructureComponent extends Component { /** * Remove a measurement given as a pair, triple, quad of atom indices */ - removeMeasurement (atomList: number[]) { + removeMeasurement(atomList: number[]) { this.pickDict.del(atomList.slice().sort()) this.measureBuild() } @@ -440,7 +440,7 @@ class StructureComponent extends Component { /** * Add a measurement given as a pair, triple, quad of atom indices */ - addMeasurement (atomList: number[]) { + addMeasurement(atomList: number[]) { if (atomList.length < 2 || atomList.length > 4) return const atomListSorted = atomList.slice().sort() if (!this.pickDict.has(atomListSorted)) { @@ -449,24 +449,37 @@ class StructureComponent extends Component { this.measureBuild() } - selectedPick (atoms: AtomProxy[]) { + selectedPick(atoms: AtomProxy[]) { let atomIndices: number[] = [] atoms.forEach(function (x) { atomIndices.push(x.index) }) + this.selectedPickIndices(atomIndices) + } + + selectedPickIndices(atomIndices: number[]) { this.selectedAtomIndices.toggleAny(atomIndices) this.selectedUpdate() } - selectedUpdate () { + setSelectedIndices(atomIndices: number[]) { + this.selectedAtomIndices.clear() + for (var i = 0; i < atomIndices.length; i++) { + this.selectedAtomIndices.add(atomIndices[i]) + } + this.selectedUpdate() + } + + + selectedUpdate() { const pickData = this.selectedAtomIndices.list const radiusData: { [k: number]: number } = {} pickData.forEach(ai => { const r = Math.max(0.1, this.getMaxRepresentationRadius(ai)) - radiusData[ ai ] = r * (2.3 - smoothstep(0.1, 2, r)) + radiusData[ai] = r * (2.3 - smoothstep(0.1, 2, r)) }) this.selectedRepresentation.setSelection( - pickData.length ? ( '@' + pickData.join(',') ) : 'none' + pickData.length ? ('@' + pickData.join(',')) : 'none' ) this.selectedRepresentation.setParameters({ radiusData }) } diff --git a/src/controls/mouse-actions.ts b/src/controls/mouse-actions.ts index acd73bff2..713f4bd33 100644 --- a/src/controls/mouse-actions.ts +++ b/src/controls/mouse-actions.ts @@ -9,7 +9,7 @@ import { almostIdentity } from '../math/math-utils' import Stage from '../stage/stage' import StructureComponent from '../component/structure-component' import SurfaceRepresentation from '../representation/surface-representation' -import AtomProxy from '../proxy/atom-proxy'; +import { SimpleSet, createSimpleSet } from '../utils'; export type ScrollCallback = (stage: Stage, delta: number) => void export type DragCallback = (stage: Stage, dx: number, dy: number) => void @@ -26,7 +26,7 @@ class MouseActions { * @param {Number} delta - amount to zoom * @return {undefined} */ - static zoomScroll (stage: Stage, delta: number) { + static zoomScroll(stage: Stage, delta: number) { stage.trackballControls.zoom(delta) } @@ -36,7 +36,7 @@ class MouseActions { * @param {Number} delta - amount to move clipping plane * @return {undefined} */ - static clipNearScroll (stage: Stage, delta: number) { + static clipNearScroll(stage: Stage, delta: number) { const sp = stage.getParameters() stage.setParameters({ clipNear: sp.clipNear + delta / 10 }) } @@ -47,7 +47,7 @@ class MouseActions { * @param {Number} delta - amount to move focus planes * @return {undefined} */ - static focusScroll (stage: Stage, delta: number) { + static focusScroll(stage: Stage, delta: number) { const sp = stage.getParameters() const focus = sp.clipNear * 2 const sign = Math.sign(delta) @@ -62,7 +62,7 @@ class MouseActions { * @param {Number} delta - amount to move focus planes and zoom * @return {undefined} */ - static zoomFocusScroll (stage: Stage, delta: number) { + static zoomFocusScroll(stage: Stage, delta: number) { stage.trackballControls.zoom(delta) const z = stage.viewer.camera.position.z stage.setFocus(100 - Math.abs(z / 8)) @@ -74,7 +74,7 @@ class MouseActions { * @param {Number} delta - amount to change isolevel * @return {undefined} */ - static isolevelScroll (stage: Stage, delta: number) { + static isolevelScroll(stage: Stage, delta: number) { const d = Math.sign(delta) / 10 stage.eachRepresentation((reprElem, comp) => { if (reprElem.repr instanceof SurfaceRepresentation) { @@ -93,7 +93,7 @@ class MouseActions { * @param {Number} dy - amount to pan in y direction * @return {undefined} */ - static panDrag (stage: Stage, dx: number, dy: number) { + static panDrag(stage: Stage, dx: number, dy: number) { stage.trackballControls.pan(dx, dy) } @@ -104,7 +104,7 @@ class MouseActions { * @param {Number} dy - amount to rotate in y direction * @return {undefined} */ - static rotateDrag (stage: Stage, dx: number, dy: number) { + static rotateDrag(stage: Stage, dx: number, dy: number) { stage.trackballControls.rotate(dx, dy) } @@ -115,7 +115,7 @@ class MouseActions { * @param {Number} dy - amount to rotate in y direction * @return {undefined} */ - static zRotateDrag (stage: Stage, dx: number, dy: number) { + static zRotateDrag(stage: Stage, dx: number, dy: number) { stage.trackballControls.zRotate(dx, dy) } @@ -126,7 +126,7 @@ class MouseActions { * @param {Number} dy - amount to zoom * @return {undefined} */ - static zoomDrag (stage: Stage, dx: number, dy: number) { + static zoomDrag(stage: Stage, dx: number, dy: number) { stage.trackballControls.zoom((dx + dy) / -2) } @@ -138,7 +138,7 @@ class MouseActions { * @param {Number} dy - amount to zoom and focus * @return {undefined} */ - static zoomFocusDrag (stage: Stage, dx: number, dy: number) { + static zoomFocusDrag(stage: Stage, dx: number, dy: number) { stage.trackballControls.zoom((dx + dy) / -2) const z = stage.viewer.camera.position.z stage.setFocus(100 - Math.abs(z / 8)) @@ -151,7 +151,7 @@ class MouseActions { * @param {Number} dy - amount to pan in y direction * @return {undefined} */ - static panComponentDrag (stage: Stage, dx: number, dy: number) { + static panComponentDrag(stage: Stage, dx: number, dy: number) { stage.trackballControls.panComponent(dx, dy) } @@ -162,7 +162,7 @@ class MouseActions { * @param {Number} dy - amount to pan in y direction * @return {undefined} */ - static panAtomDrag (stage: Stage, dx: number, dy: number) { + static panAtomDrag(stage: Stage, dx: number, dy: number) { stage.trackballControls.panAtom(dx, dy) } @@ -173,7 +173,7 @@ class MouseActions { * @param {Number} dy - amount to rotate in y direction * @return {undefined} */ - static rotateComponentDrag (stage: Stage, dx: number, dy: number) { + static rotateComponentDrag(stage: Stage, dx: number, dy: number) { stage.trackballControls.rotateComponent(dx, dy) } @@ -184,11 +184,11 @@ class MouseActions { * @param {Number} dy - amount to move in y direction * @return {undefined} */ - static moveComponentDrag (stage: Stage, dx: number, dy: number) { + static moveComponentDrag(stage: Stage, dx: number, dy: number) { stage.trackballControls.translateAtoms(dx, dy) } - static rotateSelectionDrag (stage: Stage, dx: number, dy: number) { + static rotateSelectionDrag(stage: Stage, dx: number, dy: number) { stage.trackballControls.rotateAtoms(dx, dy) } @@ -198,7 +198,7 @@ class MouseActions { * @param {PickingProxy} pickingProxy - the picking data object * @return {undefined} */ - static movePick (stage: Stage, pickingProxy: PickingProxy) { + static movePick(stage: Stage, pickingProxy: PickingProxy) { if (pickingProxy) { stage.animationControls.move(pickingProxy.position.clone()) } @@ -210,7 +210,7 @@ class MouseActions { * @param {PickingProxy} pickingProxy - the picking data object * @return {undefined} */ - static tooltipPick (stage: Stage, pickingProxy: PickingProxy) { + static tooltipPick(stage: Stage, pickingProxy: PickingProxy) { const tt = stage.tooltip const sp = stage.getParameters() as any if (sp.tooltip && pickingProxy) { @@ -224,9 +224,9 @@ class MouseActions { } } - - static measurePick (stage: Stage, pickingProxy: PickingProxy) { + + static measurePick(stage: Stage, pickingProxy: PickingProxy) { if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) { const atom = pickingProxy.atom || pickingProxy.closestBondAtom const sc = pickingProxy.component as StructureComponent @@ -242,148 +242,145 @@ class MouseActions { * @param {PickingProxy} pickingProxy - the picking data object * @return {undefined} */ - static selectPick (stage: Stage, pickingProxy: PickingProxy) { + static selectPick(stage: Stage, pickingProxy: PickingProxy) { if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) { - const atoms = [pickingProxy.atom] || pickingProxy.bond.atoms + const atoms = [pickingProxy.atom.index] || [pickingProxy.bond.atom1.index, pickingProxy.bond.atom2.index] const sc = pickingProxy.component as StructureComponent - sc.selectedPick(atoms) + sc.selectedPickIndices(atoms) } } - static selectPickAll (stage: Stage, pickingProxies: PickingProxy[], x:number, y:number) { + static selectPickAll(stage: Stage, pickingProxies: PickingProxy[], x: number, y: number) { let components: StructureComponent[] = [] - let picked: AtomProxy[][] = [] + let picked: SimpleSet[] = [] pickingProxies.forEach(function (pickingProxy) { - if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) { - let atoms = [pickingProxy.atom] || pickingProxy.bond.atoms + if (pickingProxy && pickingProxy.atom) { + let a = pickingProxy.atom.index let sc = pickingProxy.component as StructureComponent if (!components.includes(sc)) { - let _new: AtomProxy[] = [] + let _new = createSimpleSet() components.push(sc) picked.push(_new) } let j = components.indexOf(sc) - atoms.forEach(function (a) { - if (!picked[j].includes(a)) picked[j].push(a) - }) + picked[j].add(a) } }) - + console.log('picked', picked) for (var i = 0; i < components.length; i++) { - components[i].selectedPick(picked[i]) + components[i].setSelectedIndices(picked[i].list) } stage.dragSelection.moveSelection(x, y) } - static clearSelect (stage: Stage) { + static clearSelect(stage: Stage) { stage.eachComponent(function (sc: StructureComponent) { sc.selectedAtomIndices.clear() sc.selectedUpdate() }, "structure") } - static onSelectDown (stage: Stage, x: number, y: number) { - console.log('ON SELECT DOWN') + static onSelectDown(stage: Stage, x: number, y: number) { const ds = stage.dragSelection const sp = stage.getParameters() as any if (sp.dragSelection) { ds.createSelection(x, y) } else { ds.removeSelection() - console.log('rem??') } } - static onSelectDragXY (stage: Stage, x: number, y: number) { + static onSelectDragXY(stage: Stage, x: number, y: number) { const ds = stage.dragSelection ds.moveSelection(x, y) } - static onSelectUp (stage: Stage) { + static onSelectUp(stage: Stage) { stage.dragSelection.removeSelection() } } -type MouseActionPreset = [ string, MouseActionCallback ][] +type MouseActionPreset = [string, MouseActionCallback][] export const MouseActionPresets = { default: [ - // [ 'scroll', MouseActions.zoomScroll ], - // [ 'scroll-shift', MouseActions.focusScroll ], - // [ 'scroll-ctrl', MouseActions.isolevelScroll ], - // [ 'scroll-shift-ctrl', MouseActions.zoomFocusScroll ], - - // [ 'drag-left', MouseActions.rotateDrag ], - // [ 'drag-right', MouseActions.panDrag ], - // [ 'drag-ctrl-left', MouseActions.panDrag ], - // [ 'drag-ctrl-right', MouseActions.zRotateDrag ], - // [ 'drag-shift-left', MouseActions.zoomDrag ], - // [ 'drag-middle', MouseActions.zoomFocusDrag ], - - // [ 'drag-ctrl-shift-right', MouseActions.panComponentDrag ], - // [ 'drag-ctrl-shift-left', MouseActions.rotateComponentDrag ], - - // [ 'clickPick-right', MouseActions.measurePick ], - // [ 'clickPick-ctrl-left', MouseActions.measurePick ], - // [ 'clickPick-middle', MouseActions.movePick ], - // [ 'clickPick-left', MouseActions.movePick ], - // [ 'hoverPick', MouseActions.tooltipPick ] - // ] as MouseActionPreset, - // pymol: [ - // [ 'drag-left', MouseActions.rotateDrag ], - // [ 'drag-middle', MouseActions.panDrag ], - // [ 'drag-right', MouseActions.zoomDrag ], - // [ 'drag-shift-right', MouseActions.focusScroll ], - - // [ 'clickPick-ctrl+shift-middle', MouseActions.movePick ], - // [ 'hoverPick', MouseActions.tooltipPick ] - // ] as MouseActionPreset, - // coot: [ - // [ 'scroll', MouseActions.isolevelScroll ], - - // [ 'drag-left', MouseActions.rotateDrag ], - // [ 'drag-middle', MouseActions.panDrag ], - // [ 'drag-ctrl-left', MouseActions.panDrag ], - // [ 'drag-right', MouseActions.zoomFocusDrag ], - // [ 'drag-ctrl-right', MouseActions.focusScroll ], - - // [ 'clickPick-middle', MouseActions.movePick ], - // [ 'hoverPick', MouseActions.tooltipPick ] - // ] as MouseActionPreset, - // astexviewer: [ - // [ 'drag-left', MouseActions.rotateDrag ], - // [ 'drag-ctrl-left', MouseActions.panDrag ], - // [ 'drag-shift-left', MouseActions.zoomDrag ], - // [ 'scroll', MouseActions.focusScroll ], - // [ 'clickPick-middle', MouseActions.movePick ], - // [ 'hoverPick', MouseActions.tooltipPick ] - // ] as MouseActionPreset, - // iqmol: [ - [ 'scroll', MouseActions.zoomScroll ], - [ 'scroll-shift', MouseActions.focusScroll ], - [ 'scroll-ctrl', MouseActions.isolevelScroll ], - [ 'scroll-shift-ctrl', MouseActions.zoomFocusScroll ], - - [ 'press-shift-left', MouseActions.onSelectDown], - [ 'drop-shift-left', MouseActions.onSelectUp], - - [ 'drag-left', MouseActions.rotateDrag ], - [ 'drag-right', MouseActions.panDrag ], - [ 'drag-ctrl-left', MouseActions.rotateSelectionDrag ], - [ 'drag-ctrl-right', MouseActions.moveComponentDrag ], - [ 'dragXY-shift-left', MouseActions.selectPickAll ], - [ 'drag-middle', MouseActions.zoomFocusDrag ], - - [ 'clickPick-shift-left', MouseActions.selectPick ], - [ 'doubleClick-shift-left', MouseActions.clearSelect], - - [ 'clickPick-right', MouseActions.measurePick ], - [ 'clickPick-middle', MouseActions.movePick ], - [ 'hoverPick', MouseActions.tooltipPick ] + // [ 'scroll', MouseActions.zoomScroll ], + // [ 'scroll-shift', MouseActions.focusScroll ], + // [ 'scroll-ctrl', MouseActions.isolevelScroll ], + // [ 'scroll-shift-ctrl', MouseActions.zoomFocusScroll ], + + // [ 'drag-left', MouseActions.rotateDrag ], + // [ 'drag-right', MouseActions.panDrag ], + // [ 'drag-ctrl-left', MouseActions.panDrag ], + // [ 'drag-ctrl-right', MouseActions.zRotateDrag ], + // [ 'drag-shift-left', MouseActions.zoomDrag ], + // [ 'drag-middle', MouseActions.zoomFocusDrag ], + + // [ 'drag-ctrl-shift-right', MouseActions.panComponentDrag ], + // [ 'drag-ctrl-shift-left', MouseActions.rotateComponentDrag ], + + // [ 'clickPick-right', MouseActions.measurePick ], + // [ 'clickPick-ctrl-left', MouseActions.measurePick ], + // [ 'clickPick-middle', MouseActions.movePick ], + // [ 'clickPick-left', MouseActions.movePick ], + // [ 'hoverPick', MouseActions.tooltipPick ] + // ] as MouseActionPreset, + // pymol: [ + // [ 'drag-left', MouseActions.rotateDrag ], + // [ 'drag-middle', MouseActions.panDrag ], + // [ 'drag-right', MouseActions.zoomDrag ], + // [ 'drag-shift-right', MouseActions.focusScroll ], + + // [ 'clickPick-ctrl+shift-middle', MouseActions.movePick ], + // [ 'hoverPick', MouseActions.tooltipPick ] + // ] as MouseActionPreset, + // coot: [ + // [ 'scroll', MouseActions.isolevelScroll ], + + // [ 'drag-left', MouseActions.rotateDrag ], + // [ 'drag-middle', MouseActions.panDrag ], + // [ 'drag-ctrl-left', MouseActions.panDrag ], + // [ 'drag-right', MouseActions.zoomFocusDrag ], + // [ 'drag-ctrl-right', MouseActions.focusScroll ], + + // [ 'clickPick-middle', MouseActions.movePick ], + // [ 'hoverPick', MouseActions.tooltipPick ] + // ] as MouseActionPreset, + // astexviewer: [ + // [ 'drag-left', MouseActions.rotateDrag ], + // [ 'drag-ctrl-left', MouseActions.panDrag ], + // [ 'drag-shift-left', MouseActions.zoomDrag ], + // [ 'scroll', MouseActions.focusScroll ], + // [ 'clickPick-middle', MouseActions.movePick ], + // [ 'hoverPick', MouseActions.tooltipPick ] + // ] as MouseActionPreset, + // iqmol: [ + ['scroll', MouseActions.zoomScroll], + ['scroll-shift', MouseActions.focusScroll], + ['scroll-ctrl', MouseActions.isolevelScroll], + ['scroll-shift-ctrl', MouseActions.zoomFocusScroll], + + ['press-shift-left', MouseActions.onSelectDown], + ['drop-shift-left', MouseActions.onSelectUp], + ['drop-left', MouseActions.onSelectUp], + + ['drag-left', MouseActions.rotateDrag], + ['drag-right', MouseActions.panDrag], + ['drag-ctrl-left', MouseActions.rotateSelectionDrag], + ['drag-ctrl-right', MouseActions.moveComponentDrag], + ['dragXY-shift-left', MouseActions.selectPickAll], + ['drag-middle', MouseActions.zoomFocusDrag], + + ['clickPick-shift-left', MouseActions.selectPick], + ['doubleClick-shift-left', MouseActions.clearSelect], + + ['clickPick-right', MouseActions.measurePick], + ['clickPick-middle', MouseActions.movePick], + ['hoverPick', MouseActions.tooltipPick] ] as MouseActionPreset } diff --git a/src/controls/picking-controls.ts b/src/controls/picking-controls.ts index bbccb6f6d..11a710471 100644 --- a/src/controls/picking-controls.ts +++ b/src/controls/picking-controls.ts @@ -14,7 +14,7 @@ import Viewer from '../viewer/viewer' class PickingControls { viewer: Viewer - constructor (readonly stage: Stage) { + constructor(readonly stage: Stage) { this.viewer = stage.viewer } @@ -24,12 +24,12 @@ class PickingControls { * @param {Number} y - canvas y coordinate * @return {PickingProxy|undefined} picking proxy */ - pick (x: number, y: number) { + pick(x: number, y: number) { const pickingData = this.viewer.pick(x, y) if (pickingData.picker && - pickingData.picker.type !== 'ignore' && - pickingData.pid !== undefined + pickingData.picker.type !== 'ignore' && + pickingData.pid !== undefined ) { const pickerArray = pickingData.picker.array if (pickerArray && pickingData.pid >= pickerArray.length) { @@ -40,26 +40,23 @@ class PickingControls { } } - pickAll (x0: number, y0: number, dx: number, dy: number) { - const pickedData = this.viewer.pickAll(x0, y0, dx, dy) - console.log('PICKED DATA IS', pickedData) + pickAll(x0: number, y0: number, x1: number, y1: number) { + const pickedData = this.viewer.pickAll(x0, y0, x1, y1) let picked: PickingProxy[] = [] for (var i = 0; i < pickedData.length; i++) { let pickingData = pickedData[i] - if (pickingData.picker && - pickingData.picker.type !== 'ignore' && - pickingData.pid !== undefined + if (pickingData.picker.type !== 'ignore' && + pickingData.pid !== undefined ) { let pickerArray = pickingData.picker.array if (pickerArray && pickingData.pid >= pickerArray.length) { console.error('pid >= picker.array.length') } else { - picked.push( new PickingProxy(pickingData, this.stage) ) + picked.push(new PickingProxy(pickingData, this.stage)) } } } - return picked } } diff --git a/src/stage/mouse-observer.ts b/src/stage/mouse-observer.ts index 3f32170cf..673ecd586 100644 --- a/src/stage/mouse-observer.ts +++ b/src/stage/mouse-observer.ts @@ -25,14 +25,14 @@ import MouseControls from '../controls/mouse-controls' * @property {Signal} hovered - on hover */ -function getTouchDistance (event: TouchEvent) { - const dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX - const dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY +function getTouchDistance(event: TouchEvent) { + const dx = event.touches[0].pageX - event.touches[1].pageX + const dy = event.touches[0].pageY - event.touches[1].pageY return Math.sqrt(dx * dx + dy * dy) } -function getMouseButtons (event: MouseEvent) { - if (typeof event === 'object') { +function getMouseButtons(event: MouseEvent) { + if (typeof event === 'object') { if ('buttons' in event) { return event.buttons } else if ('which' in event as any) { @@ -72,7 +72,7 @@ export interface MouseSignals { export interface MouseParams { hoverTimeout?: number - handleScroll?:boolean + handleScroll?: boolean doubleClickSpeed?: number } @@ -117,7 +117,7 @@ class MouseObserver { } hoverTimeout: number - handleScroll:boolean + handleScroll: boolean doubleClickSpeed: number viewer: Viewer @@ -134,9 +134,9 @@ class MouseObserver { hovering = true // Flag indicating if the mouse is hovering scrolled = false // Flag indicating if there was a scolling event since the last mouse move lastMoved = Infinity // Timestamp of last mouse move - which? = 0 // 0: No button; 1: Left button; 2: Middle button; 3: Right button - buttons? = 0 // 0: No button; 1: Left button; 2: Right button; 4: Middle button - pressed? = false // Flag indicating if the mouse is pressed down + which?= 0 // 0: No button; 1: Left button; 2: Middle button; 3: Right button + buttons?= 0 // 0: No button; 1: Left button; 2: Right button; 4: Middle button + pressed?= false // Flag indicating if the mouse is pressed down altKey = false // Flag indicating if the alt key is pressed ctrlKey = false // Flag indicating if the ctrl key is pressed metaKey = false // Flag indicating if the meta key is pressed @@ -155,7 +155,7 @@ class MouseObserver { * @param {Boolean} params.handleScroll - whether or not to handle scroll events * @param {Integer} params.doubleClickSpeed - max time in ms to trigger double click */ - constructor (readonly domElement: HTMLCanvasElement, params: MouseParams = {}) { + constructor(readonly domElement: HTMLCanvasElement, params: MouseParams = {}) { this.domElement.style.touchAction = 'none' this.hoverTimeout = defaults(params.hoverTimeout, 50) @@ -187,7 +187,7 @@ class MouseObserver { document.addEventListener('touchmove', this._onTouchmove, opt) } - get key () { + get key() { let key = 0 if (this.altKey) key += 1 if (this.ctrlKey) key += 2 @@ -196,7 +196,7 @@ class MouseObserver { return key } - setParameters (params: MouseParams = {}) { + setParameters(params: MouseParams = {}) { this.hoverTimeout = defaults(params.hoverTimeout, this.hoverTimeout) } @@ -206,7 +206,7 @@ class MouseObserver { * @emits {MouseSignals.hovered} when hovered * @return {undefined} */ - _listen () { + _listen() { const now = window.performance.now() const cp = this.canvasPosition if (this.doubleClickPending && now - this.lastClicked > this.doubleClickSpeed) { @@ -231,7 +231,7 @@ class MouseObserver { * @param {Event} event - mouse event * @return {undefined} */ - _onMousewheel (event: MouseWheelEvent) { + _onMousewheel(event: MouseWheelEvent) { if (event.target !== this.domElement || !this.handleScroll) { return } @@ -264,7 +264,7 @@ class MouseObserver { * @param {Event} event - mouse event * @return {undefined} */ - _onMousemove (event: MouseEvent) { + _onMousemove(event: MouseEvent) { if (event.target === this.domElement) { event.preventDefault() this.overElement = true @@ -288,11 +288,11 @@ class MouseObserver { this.prevPosition.y, this.position.x, this.position.y - ) + ) } } - _onMousedown (event: MouseEvent) { + _onMousedown(event: MouseEvent) { if (event.target !== this.domElement) { return } @@ -316,10 +316,11 @@ class MouseObserver { * @param {Event} event - mouse event * @return {undefined} */ - _onMouseup (event: MouseEvent) { + _onMouseup(event: MouseEvent) { if (event.target === this.domElement) { event.preventDefault() } + this.signals.dropped.dispatch(); this._setKeys(event) const cp = this.canvasPosition if (this._distance() < 4) { @@ -329,7 +330,6 @@ class MouseObserver { this.doubleClickPending = false } this.signals.clicked.dispatch(cp.x, cp.y) - this.signals.dropped.dispatch(); this.doubleClickPending = true this.prevClickCP.copy(cp) } @@ -341,13 +341,13 @@ class MouseObserver { // } } - _onContextmenu (event: MouseEvent) { + _onContextmenu(event: MouseEvent) { if (event.target === this.domElement) { event.preventDefault() } } - _onTouchstart (event: TouchEvent) { + _onTouchstart(event: TouchEvent) { if (event.target !== this.domElement) { return } @@ -358,32 +358,32 @@ class MouseObserver { this.moving = false this.hovering = false this.down.set( - event.touches[ 0 ].pageX, - event.touches[ 0 ].pageY + event.touches[0].pageX, + event.touches[0].pageY ) this.position.set( - event.touches[ 0 ].pageX, - event.touches[ 0 ].pageY + event.touches[0].pageX, + event.touches[0].pageY ) - this._setCanvasPosition(event.touches[ 0 ]) + this._setCanvasPosition(event.touches[0]) break } case 2: { this.down.set( - (event.touches[ 0 ].pageX + event.touches[ 1 ].pageX) / 2, - (event.touches[ 0 ].pageY + event.touches[ 1 ].pageY) / 2 + (event.touches[0].pageX + event.touches[1].pageX) / 2, + (event.touches[0].pageY + event.touches[1].pageY) / 2 ) this.position.set( - (event.touches[ 0 ].pageX + event.touches[ 1 ].pageX) / 2, - (event.touches[ 0 ].pageY + event.touches[ 1 ].pageY) / 2 + (event.touches[0].pageX + event.touches[1].pageX) / 2, + (event.touches[0].pageY + event.touches[1].pageY) / 2 ) this.lastTouchDistance = getTouchDistance(event) } } } - _onTouchend (event: TouchEvent) { + _onTouchend(event: TouchEvent) { if (event.target === this.domElement) { event.preventDefault() } @@ -392,7 +392,7 @@ class MouseObserver { this.pressed = undefined } - _onTouchmove (event: TouchEvent) { + _onTouchmove(event: TouchEvent) { if (event.target === this.domElement) { event.preventDefault() this.overElement = true @@ -409,21 +409,19 @@ class MouseObserver { this.lastMoved = window.performance.now() this.prevPosition.copy(this.position) this.position.set( - event.touches[ 0 ].pageX, - event.touches[ 0 ].pageY + event.touches[0].pageX, + event.touches[0].pageY ) - this._setCanvasPosition(event.touches[ 0 ]) + this._setCanvasPosition(event.touches[0]) const dx = this.prevPosition.x - this.position.x const dy = this.prevPosition.y - this.position.y this.signals.moved.dispatch(dx, dy) if (this.pressed) { this.signals.dragged.dispatch(dx, dy) this.signals.draggedXY.dispatch( - this.prevPosition.x, - this.prevPosition.y, this.position.x, this.position.y - ) + ) } break } @@ -434,11 +432,11 @@ class MouseObserver { this.lastTouchDistance = touchDistance this.prevPosition.copy(this.position) this.position.set( - (event.touches[ 0 ].pageX + event.touches[ 1 ].pageX) / 2, - (event.touches[ 0 ].pageY + event.touches[ 1 ].pageY) / 2 + (event.touches[0].pageX + event.touches[1].pageX) / 2, + (event.touches[0].pageY + event.touches[1].pageY) / 2 ) if (Math.abs(delta) > 2 && this.handleScroll && - this.position.distanceTo(this.prevPosition) < 2 + this.position.distanceTo(this.prevPosition) < 2 ) { this.which = 0 this.buttons = 0 @@ -456,18 +454,18 @@ class MouseObserver { this.prevPosition.y, this.position.x, this.position.y - ) + ) } } } } } - _distance () { + _distance() { return this.position.distanceTo(this.down) } - _setCanvasPosition (event: any) { // TODO + _setCanvasPosition(event: any) { // TODO const box = this.domElement.getBoundingClientRect() let offsetX, offsetY if ('offsetX' in event && 'offsetY' in event) { @@ -480,14 +478,14 @@ class MouseObserver { this.canvasPosition.set(offsetX, box.height - offsetY) } - _setKeys (event: MouseEvent|TouchEvent) { + _setKeys(event: MouseEvent | TouchEvent) { this.altKey = event.altKey this.ctrlKey = event.ctrlKey this.metaKey = event.metaKey this.shiftKey = event.shiftKey } - dispose () { + dispose() { document.removeEventListener('mousewheel', this._onMousewheel) document.removeEventListener('wheel', this._onMousewheel) document.removeEventListener('MozMousePixelScroll', this._onMousewheel) diff --git a/src/stage/selecting-behavior.ts b/src/stage/selecting-behavior.ts index c38b9a9ff..e3d3c2a9a 100644 --- a/src/stage/selecting-behavior.ts +++ b/src/stage/selecting-behavior.ts @@ -14,7 +14,7 @@ class SelectingBehavior { mouse: MouseObserver controls: MouseControls - constructor (readonly stage: Stage) { + constructor(readonly stage: Stage) { this.stage = stage this.mouse = stage.mouseObserver this.controls = stage.mouseControls @@ -32,18 +32,20 @@ class SelectingBehavior { // this.controls.run('clickPick', pickingProxy) // } - _onPress (x: number, y: number) { + _onPress(x: number, y: number) { this.controls.run('press', x, y) } - _onDrop () { + _onDrop() { this.controls.run('drop') } - _onDragXY (x0: number, y0: number, x1: number, y1: number) { + _onDragXY(x1: number, y1: number) { // const sp = this.stage.getParameters() as any if (this.stage.dragSelection.isDown) { - let pickedProxies = this.stage.pickingControls.pickAll(x0, y0, x1-x0, y1-y0) + const x0 = this.stage.dragSelection.startPoint.x + const y0 = this.stage.dragSelection.startPoint.y + let pickedProxies = this.stage.pickingControls.pickAll(x0, y0, x1, y1) this.controls.run('dragXY', pickedProxies, x1, y1) } } @@ -52,7 +54,7 @@ class SelectingBehavior { // this.controls.run('doubleClick') // } - dispose () { + dispose() { // this.mouse.signals.clicked.remove(this._onClick, this) this.mouse.signals.pressed.remove(this._onPress, this) this.mouse.signals.draggedXY.remove(this._onDragXY, this) diff --git a/src/utils/toggle-set.ts b/src/utils/toggle-set.ts index d52b41deb..ce83f1c49 100644 --- a/src/utils/toggle-set.ts +++ b/src/utils/toggle-set.ts @@ -4,7 +4,7 @@ * @private */ - export interface ToggleSet { +export interface ToggleSet { has: (value: T) => boolean add: (value: T) => void del: (value: T) => void @@ -15,20 +15,20 @@ clear: () => void } -export function createToggleSet (): ToggleSet { +export function createToggleSet(): ToggleSet { const list: T[] = [] return { has: function (value: T) { return list.indexOf(value) !== -1 }, - add: function (value: T) { + add: function (value: T) { if (list.indexOf(value) === -1) { list.push(value) - } + } }, - del: function (value: T) { + del: function (value: T) { if (list.indexOf(value) !== -1) { list.splice(list.indexOf(value), 1) - } + } }, toggle: function (value: T) { if (this.has(value)) { @@ -40,22 +40,32 @@ export function createToggleSet (): ToggleSet { toggleAny: function (values: T[]) { let addAll = false; for (var i = 0; i < values.length; i++) { - if (!this.has(values[i])) addAll = true; + console.log('toggle', list, values[i], addAll, list.includes(values[i])) + if (!list.includes(values[i])) { + addAll = true; + } } - let action if (addAll) { - action = this.add + for (var i = 0; i < values.length; i++) { + let value = values[i] + if (!list.includes(value)) { + list.push(value) + } + } } else { - action = this.del + console.log('deleting') + for (var i = 0; i < values.length; i++) { + let value = values[i] + if (list.indexOf(value) !== -1) { + list.splice(list.indexOf(value), 1) + } + } } - for (var i = 0; i < values.length; i++) { - action(values[i]) - } }, - get count () { return list.length }, - get list () {return list}, + get count() { return list.length }, + get list() { return list }, clear: function () { list.splice(0) } diff --git a/src/viewer/drag-selection.ts b/src/viewer/drag-selection.ts index 7c46f6ab2..d5ab103b7 100644 --- a/src/viewer/drag-selection.ts +++ b/src/viewer/drag-selection.ts @@ -11,38 +11,37 @@ export default class DragSelection { viewer: Viewer element: HTMLElement - startPoint: {x: number, y: number}; - pointTopLeft: {x: number, y: number}; - pointBottomRight: {x: number, y: number}; + startPoint: { x: number, y: number }; + pointTopLeft: { x: number, y: number }; + pointBottomRight: { x: number, y: number }; isDown: Boolean; - constructor (viewer: Viewer) { + constructor(viewer: Viewer) { this.viewer = viewer; this.element = document.createElement('div'); Object.assign(this.element.style, { - display: 'none', - position: 'fixed', - zIndex: '1000000', - pointerEvents: 'none', - border: '1px solid #55aaff', - backgroundColor: 'rgba(75, 160, 255, 0.3)', - }) + display: 'none', + position: 'fixed', + zIndex: '1000000', + pointerEvents: 'none', + border: '1px solid #55aaff', + backgroundColor: 'rgba(75, 160, 255, 0.3)', + }) this.viewer.container.appendChild(this.element) this.startPoint = { x: 0, y: 0 }; this.pointTopLeft = { x: 0, y: 0 }; this.pointBottomRight = { x: 0, y: 0 }; - + //TODO TOGGLE SET this.isDown = false; } - createSelection (x: number, y: number) { - console.log('creatin gsel') + createSelection(x: number, y: number) { this.element.style.display = 'block'; this.element.style.left = x + 'px'; this.element.style.top = y + 'px'; @@ -55,26 +54,24 @@ export default class DragSelection { this.isDown = true; } - moveSelection (x: number, y: number) { + moveSelection(x: number, y: number) { if (!this.isDown) return; - console.log('mv seling') - this.pointBottomRight.x = Math.max( this.startPoint.x, x ); - this.pointBottomRight.y = Math.max( this.startPoint.y, y ); - this.pointTopLeft.x = Math.min( this.startPoint.x, x ); - this.pointTopLeft.y = Math.min( this.startPoint.y, y ); + this.pointBottomRight.x = Math.max(this.startPoint.x, x); + this.pointBottomRight.y = Math.max(this.startPoint.y, y); + this.pointTopLeft.x = Math.min(this.startPoint.x, x); + this.pointTopLeft.y = Math.min(this.startPoint.y, y); this.element.style.left = this.pointTopLeft.x + 'px'; this.element.style.top = this.pointTopLeft.y + 'px'; - this.element.style.width = ( this.pointBottomRight.x - this.pointTopLeft.x ) + 'px'; - this.element.style.height = ( this.pointBottomRight.y - this.pointTopLeft.y ) + 'px'; + this.element.style.width = (this.pointBottomRight.x - this.pointTopLeft.x) + 'px'; + this.element.style.height = (this.pointBottomRight.y - this.pointTopLeft.y) + 'px'; } - removeSelection () { - console.log('removed') + removeSelection() { this.element.style.display = 'none'; this.isDown = false; } - + } \ No newline at end of file diff --git a/src/viewer/viewer.ts b/src/viewer/viewer.ts index f7062d85b..d3c99aae7 100644 --- a/src/viewer/viewer.ts +++ b/src/viewer/viewer.ts @@ -48,12 +48,12 @@ const pixelBufferUint = new Uint8Array(4 * 25) // This starts at the center and tries successively further points. // (Many points will be at equal distance to the center, their order // is arbitrary). -const pixelOrder = [12,7,13,17,11,6,8,18,16,2,14,22,10,1,3,9,19,23,21,15,5,0,4,24,20] +const pixelOrder = [12, 7, 13, 17, 11, 6, 8, 18, 16, 2, 14, 22, 10, 1, 3, 9, 19, 23, 21, 15, 5, 0, 4, 24, 20] const tmpMatrix = new Matrix4() -function onBeforeRender (this: Object3D, renderer: WebGLRenderer, scene: Scene, camera: PerspectiveCamera|OrthographicCamera, geometry: Geometry, material: ShaderMaterial/*, group */) { +function onBeforeRender(this: Object3D, renderer: WebGLRenderer, scene: Scene, camera: PerspectiveCamera | OrthographicCamera, geometry: Geometry, material: ShaderMaterial/*, group */) { const u = material.uniforms const updateList = [] @@ -63,7 +63,7 @@ function onBeforeRender (this: Object3D, renderer: WebGLRenderer, scene: Scene, } if (u.modelViewMatrixInverse || u.modelViewMatrixInverseTranspose || - u.modelViewProjectionMatrix || u.modelViewProjectionMatrixInverse + u.modelViewProjectionMatrix || u.modelViewProjectionMatrixInverse ) { this.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, this.matrixWorld) } @@ -122,13 +122,13 @@ function onBeforeRender (this: Object3D, renderer: WebGLRenderer, scene: Scene, const pu = p.getUniforms() updateList.forEach(function (name) { - pu.setValue(gl, name, u[ name ].value) + pu.setValue(gl, name, u[name].value) }) } } } -export type CameraType = 'perspective'|'orthographic'|'stereo' +export type CameraType = 'perspective' | 'orthographic' | 'stereo' export interface ViewerSignals { ticked: Signal, @@ -189,7 +189,7 @@ export default class Viewer { perspectiveCamera: PerspectiveCamera private orthographicCamera: OrthographicCamera private stereoCamera: StereoCamera - camera: PerspectiveCamera|OrthographicCamera + camera: PerspectiveCamera | OrthographicCamera width: number height: number @@ -240,7 +240,7 @@ export default class Viewer { private distVector = new Vector3() - constructor (idOrElement: string|HTMLElement) { + constructor(idOrElement: string | HTMLElement) { this.signals = { ticked: new Signal(), rendered: new Signal() @@ -250,7 +250,7 @@ export default class Viewer { const elm = document.getElementById(idOrElement) if (elm === null) { this.container = document.createElement('div') - }else { + } else { this.container = elm } } else if (idOrElement instanceof HTMLElement) { @@ -292,7 +292,7 @@ export default class Viewer { this.animate = this.animate.bind(this) } - private _initParams () { + private _initParams() { this.parameters = { fogColor: new Color(0x000000), fogNear: 50, @@ -318,9 +318,9 @@ export default class Viewer { } } - private _initCamera () { + private _initCamera() { const lookAt = new Vector3(0, 0, 0) - const {width, height} = this + const { width, height } = this this.perspectiveCamera = new PerspectiveCamera( this.parameters.cameraFov, width / height @@ -341,7 +341,7 @@ export default class Viewer { const cameraType = this.parameters.cameraType if (cameraType === 'orthographic') { this.camera = this.orthographicCamera - } else if(cameraType === 'perspective' || cameraType === 'stereo') { + } else if (cameraType === 'perspective' || cameraType === 'stereo') { this.camera = this.perspectiveCamera } else { throw new Error(`Unknown cameraType '${cameraType}'`) @@ -349,11 +349,11 @@ export default class Viewer { this.camera.updateProjectionMatrix() } - private _initStats () { + private _initStats() { this.stats = new Stats() } - private _initScene () { + private _initScene() { if (!this.scene) { this.scene = new Scene() this.scene.name = 'scene' @@ -400,9 +400,9 @@ export default class Viewer { this.scene.add(this.ambientLight) } - private _initRenderer () { + private _initRenderer() { const dpr = window.devicePixelRatio - const {width, height} = this + const { width, height } = this try { this.renderer = new WebGLRenderer({ @@ -527,7 +527,7 @@ export default class Viewer { )) } - private _initHelper () { + private _initHelper() { const indices = new Uint16Array([ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 @@ -547,19 +547,19 @@ export default class Viewer { this.helperGroup.add(this.boundingBoxMesh) } - updateHelper () { + updateHelper() { const position = ((this.boundingBoxMesh.geometry as BufferGeometry).attributes as any).position // TODO const array = position.array - const {min, max} = this.boundingBox + const { min, max } = this.boundingBox - array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z - array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z - array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z - array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z - array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z - array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z - array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z - array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z + array[0] = max.x; array[1] = max.y; array[2] = max.z + array[3] = min.x; array[4] = max.y; array[5] = max.z + array[6] = min.x; array[7] = min.y; array[8] = max.z + array[9] = max.x; array[10] = min.y; array[11] = max.z + array[12] = max.x; array[13] = max.y; array[14] = min.z + array[15] = min.x; array[16] = max.y; array[17] = min.z + array[18] = min.x; array[19] = min.y; array[20] = min.z + array[21] = max.x; array[22] = min.y; array[23] = min.z position.needsUpdate = true @@ -568,7 +568,7 @@ export default class Viewer { } } - add (buffer: Buffer, instanceList?: BufferInstance[]) { + add(buffer: Buffer, instanceList?: BufferInstance[]) { // Log.time( "Viewer.add" ); if (instanceList) { @@ -594,10 +594,10 @@ export default class Viewer { // Log.timeEnd( "Viewer.add" ); } - addBuffer (buffer: Buffer, instance?: BufferInstance) { + addBuffer(buffer: Buffer, instance?: BufferInstance) { // Log.time( "Viewer.addBuffer" ); - function setUserData (object: Object3D) { + function setUserData(object: Object3D) { if (object instanceof Group) { object.children.forEach(setUserData) } else { @@ -647,7 +647,7 @@ export default class Viewer { // Log.timeEnd( "Viewer.addBuffer" ); } - remove (buffer: Buffer) { + remove(buffer: Buffer) { this.translationGroup.children.forEach(function (group) { group.remove(buffer.group) group.remove(buffer.wireframeGroup) @@ -663,10 +663,10 @@ export default class Viewer { // this.requestRender(); } - private _updateBoundingBox (geometry?: BufferGeometry, matrix?: Matrix4, instanceMatrix?: Matrix4) { + private _updateBoundingBox(geometry?: BufferGeometry, matrix?: Matrix4, instanceMatrix?: Matrix4) { const boundingBox = this.boundingBox - function updateGeometry (geometry: BufferGeometry, matrix?: Matrix4, instanceMatrix?: Matrix4) { + function updateGeometry(geometry: BufferGeometry, matrix?: Matrix4, instanceMatrix?: Matrix4) { if (!geometry.boundingBox) { geometry.computeBoundingBox() } @@ -689,7 +689,7 @@ export default class Viewer { boundingBox.union(geoBoundingBox) } - function updateNode (node: Mesh) { + function updateNode(node: Mesh) { if (node.geometry !== undefined) { let matrix, instanceMatrix if (node.userData.buffer) { @@ -714,13 +714,13 @@ export default class Viewer { this.boundingBoxLength = this.boundingBoxSize.length() } - updateBoundingBox () { + updateBoundingBox() { this._updateBoundingBox() if (Debug) this.updateHelper() } - getPickingPixels () { - const {width, height} = this + getPickingPixels() { + const { width, height } = this const n = width * height * 4 const imgBuffer = SupportsReadPixelsFloat ? new Float32Array(n) : new Uint8Array(n) @@ -733,17 +733,17 @@ export default class Viewer { return imgBuffer } - getImage (picking: boolean) { + getImage(picking: boolean) { return new Promise(resolve => { if (picking) { - const {width, height} = this + const { width, height } = this const n = width * height * 4 let imgBuffer = this.getPickingPixels() if (SupportsReadPixelsFloat) { const imgBuffer2 = new Uint8Array(n) for (let i = 0; i < n; ++i) { - imgBuffer2[ i ] = Math.round(imgBuffer[ i ] * 255) + imgBuffer2[i] = Math.round(imgBuffer[i] * 255) } imgBuffer = imgBuffer2 } @@ -762,11 +762,11 @@ export default class Viewer { }) } - makeImage (params: Partial = {}) { + makeImage(params: Partial = {}) { return makeImage(this, params) } - setLight (color: Color|number|string, intensity: number, ambientColor: Color|number|string, ambientIntensity: number) { + setLight(color: Color | number | string, intensity: number, ambientColor: Color | number | string, ambientIntensity: number) { const p = this.parameters if (color !== undefined) p.lightColor.set(color as string) // TODO @@ -777,7 +777,7 @@ export default class Viewer { this.requestRender() } - setFog (color?: Color|number|string, near?: number, far?: number) { + setFog(color?: Color | number | string, near?: number, far?: number) { const p = this.parameters if (color !== undefined) p.fogColor.set(color as string) // TODO @@ -787,7 +787,7 @@ export default class Viewer { this.requestRender() } - setBackground (color?: Color|number|string) { + setBackground(color?: Color | number | string) { const p = this.parameters if (color) p.backgroundColor.set(color as string) // TODO @@ -799,7 +799,7 @@ export default class Viewer { this.requestRender() } - setSampling (level: number) { + setSampling(level: number) { if (level !== undefined) { this.parameters.sampleLevel = level this.sampleLevel = level @@ -808,7 +808,7 @@ export default class Viewer { this.requestRender() } - setCamera (type: CameraType, fov?: number, eyeSep?: number) { + setCamera(type: CameraType, fov?: number, eyeSep?: number) { const p = this.parameters if (type) p.cameraType = type @@ -839,7 +839,7 @@ export default class Viewer { this.requestRender() } - setClip (near: number, far: number, dist: number) { + setClip(near: number, far: number, dist: number) { const p = this.parameters if (near !== undefined) p.clipNear = near @@ -849,7 +849,7 @@ export default class Viewer { this.requestRender() } - setSize (width: number, height: number) { + setSize(width: number, height: number) { this.width = width || 1 this.height = height || 1 @@ -875,7 +875,7 @@ export default class Viewer { this.requestRender() } - handleResize () { + handleResize() { if (this.container === document.body) { this.setSize(window.innerWidth, window.innerHeight) } else { @@ -884,7 +884,7 @@ export default class Viewer { } } - updateInfo (reset?: boolean) { + updateInfo(reset?: boolean) { const { memory, render } = this.info if (reset) { @@ -909,7 +909,7 @@ export default class Viewer { } } - animate () { + animate() { this.signals.ticked.dispatch(this.stats) const delta = window.performance.now() - this.stats.startTime @@ -926,7 +926,7 @@ export default class Viewer { window.requestAnimationFrame(this.animate) } - pick (x: number, y: number) { + pick(x: number, y: number) { if (this.parameters.cameraType === 'stereo') { // TODO picking broken for stereo camera return { @@ -954,7 +954,7 @@ export default class Viewer { const offset = pixelOrder[i] * 4 - const oid = Math.round(pixelBuffer[ offset + 3 ]) + const oid = Math.round(pixelBuffer[offset + 3]) const object = this.pickingGroup.getObjectById(oid) if (object) { instance = object.userData.instance @@ -993,7 +993,7 @@ export default class Viewer { return { pid, instance, picker } } - pickAll (x0: number, y0: number, dx: number, dy: number) { + pickAll(x0: number, y0: number, x1: number, y1: number) { if (this.parameters.cameraType === 'stereo') { // TODO picking broken for stereo camera @@ -1004,14 +1004,17 @@ export default class Viewer { x0 *= window.devicePixelRatio y0 *= window.devicePixelRatio - dx *= window.devicePixelRatio - dy *= window.devicePixelRatio + x1 *= window.devicePixelRatio + y1 *= window.devicePixelRatio + + let x = Math.max(x0 - 2, x1 - 2, 0) + let y = Math.min(y0 - 2, y1 - 2, 0) + - let x = Math.min(x0, x0 + dx) - let y = Math.min(y0, y0 + dy) + let px = Math.abs(x1 - x0) + 5 + let py = Math.abs(y1 - y0) + 5 - let px = Math.abs(dx) - let py = Math.abs(dy) + console.log(x0, y0, x1, y1, x, y, px, py) let _pixelBufferFloat = new Float32Array(4 * px * py) let _pixelBufferUint = new Uint8Array(4 * px * py) @@ -1022,12 +1025,13 @@ export default class Viewer { this.pickingTarget, x, y, px, py, pixelBuffer ) - for (let i = 0; i < px*py; i++) { + for (let i = 0; i < px * py; i++) { - let pid = 0, instance, picker - const offset = i * 4 + let pid: number = 0, instance, picker - const oid = Math.round(pixelBuffer[ offset + 3 ]) + let offset = i * 4 + + const oid = Math.round(pixelBuffer[offset + 3]) const object = this.pickingGroup.getObjectById(oid) if (object) { instance = object.userData.instance @@ -1036,6 +1040,8 @@ export default class Viewer { continue } + if (!picker) continue; + if (SupportsReadPixelsFloat) { pid = ((Math.round(pixelBuffer[offset] * 255) << 16) & 0xFF0000) | @@ -1053,7 +1059,7 @@ export default class Viewer { return picked } - requestRender () { + requestRender() { if (this.renderPending) { // Log.info("there is still a 'render' call pending") return @@ -1073,13 +1079,13 @@ export default class Viewer { }) } - updateZoom () { + updateZoom() { const fov = degToRad(this.perspectiveCamera.fov) const height = 2 * Math.tan(fov / 2) * -this.camera.position.z this.orthographicCamera.zoom = this.height / height } - private __updateClipping () { + private __updateClipping() { const p = this.parameters // clipping @@ -1128,7 +1134,7 @@ export default class Viewer { } } - private __updateCamera () { + private __updateCamera() { const camera = this.camera camera.updateMatrix() camera.updateMatrixWorld(true) @@ -1138,14 +1144,14 @@ export default class Viewer { sortProjectedPosition(this.scene, camera) } - private __setVisibility (model: boolean, picking: boolean, background: boolean, helper: boolean) { + private __setVisibility(model: boolean, picking: boolean, background: boolean, helper: boolean) { this.modelGroup.visible = model this.pickingGroup.visible = picking this.backgroundGroup.visible = background this.helperGroup.visible = helper } - private __updateLights () { + private __updateLights() { this.spotLight.color.set(this.parameters.lightColor) this.spotLight.intensity = this.parameters.lightIntensity @@ -1156,7 +1162,7 @@ export default class Viewer { this.ambientLight.intensity = this.parameters.ambientIntensity } - private __renderPickingGroup (camera: PerspectiveCamera|OrthographicCamera) { + private __renderPickingGroup(camera: PerspectiveCamera | OrthographicCamera) { this.renderer.clearTarget(this.pickingTarget, true, true, true) this.__setVisibility(false, true, false, false) this.renderer.render(this.scene, camera, this.pickingTarget) @@ -1173,7 +1179,7 @@ export default class Viewer { // } } - private __renderModelGroup (camera: PerspectiveCamera|OrthographicCamera, renderTarget?: WebGLRenderTarget) { + private __renderModelGroup(camera: PerspectiveCamera | OrthographicCamera, renderTarget?: WebGLRenderTarget) { if (renderTarget) { this.renderer.clearTarget(renderTarget, true, true, true) } else { @@ -1194,14 +1200,14 @@ export default class Viewer { this.updateInfo() } - private __renderSuperSample (camera: PerspectiveCamera|OrthographicCamera) { + private __renderSuperSample(camera: PerspectiveCamera | OrthographicCamera) { // based on the Supersample Anti-Aliasing Render Pass // contributed to three.js by bhouston / http://clara.io/ // // This manual approach to SSAA re-renders the scene ones for // each sample with camera jitter and accumulates the results. // References: https://en.wikipedia.org/wiki/Supersampling - const offsetList = JitterVectors[ Math.max(0, Math.min(this.sampleLevel, 5)) ] + const offsetList = JitterVectors[Math.max(0, Math.min(this.sampleLevel, 5))] const baseSampleWeight = 1.0 / offsetList.length const roundingRange = 1 / 32 @@ -1217,9 +1223,9 @@ export default class Viewer { // render the scene multiple times, each slightly jitter offset // from the last and accumulate the results. for (let i = 0; i < offsetList.length; ++i) { - const offset = offsetList[ i ] + const offset = offsetList[i] camera.setViewOffset( - width, height, offset[ 0 ], offset[ 1 ], width, height + width, height, offset[0], offset[1], width, height ) camera.updateProjectionMatrix() updateCameraUniforms(this.scene, camera) @@ -1247,7 +1253,7 @@ export default class Viewer { this.renderer.render(this.compositeScene, this.compositeCamera, null!, true) } - private __renderStereo (picking = false) { + private __renderStereo(picking = false) { const stereoCamera = this.stereoCamera stereoCamera.update(this.perspectiveCamera); @@ -1270,7 +1276,7 @@ export default class Viewer { renderer.setViewport(0, 0, size.width, size.height) } - private __render(picking = false, camera: PerspectiveCamera|OrthographicCamera) { + private __render(picking = false, camera: PerspectiveCamera | OrthographicCamera) { if (picking) { if (!this.lastRenderedPicking) this.__renderPickingGroup(camera) } else if (this.sampleLevel > 0 && this.parameters.cameraType !== 'stereo') { @@ -1281,7 +1287,7 @@ export default class Viewer { } } - render (picking = false) { + render(picking = false) { if (this.rendering) { Log.warn("'tried to call 'render' from within 'render'") return @@ -1312,14 +1318,14 @@ export default class Viewer { // Log.log(this.info.memory, this.info.render) } - clear () { + clear() { Log.log('scene cleared') this.scene.remove(this.rotationGroup) this._initScene() this.renderer.clear() } - dispose () { + dispose() { this.renderer.dispose() } } \ No newline at end of file From c645b04673740c963cabb27969bee64bbba43853 Mon Sep 17 00:00:00 2001 From: Lily Wang Date: Wed, 8 May 2019 13:55:48 +1000 Subject: [PATCH 07/16] current --- src/controls/mouse-actions.ts | 9 +++------ src/stage/mouse-observer.ts | 7 ++++--- src/viewer/viewer.ts | 8 +++++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/controls/mouse-actions.ts b/src/controls/mouse-actions.ts index 713f4bd33..5d0ab30c2 100644 --- a/src/controls/mouse-actions.ts +++ b/src/controls/mouse-actions.ts @@ -254,6 +254,8 @@ class MouseActions { let components: StructureComponent[] = [] let picked: SimpleSet[] = [] + stage.dragSelection.moveSelection(x, y) + pickingProxies.forEach(function (pickingProxy) { if (pickingProxy && pickingProxy.atom) { let a = pickingProxy.atom.index @@ -274,7 +276,7 @@ class MouseActions { components[i].setSelectedIndices(picked[i].list) } - stage.dragSelection.moveSelection(x, y) + } static clearSelect(stage: Stage) { @@ -294,11 +296,6 @@ class MouseActions { } } - static onSelectDragXY(stage: Stage, x: number, y: number) { - const ds = stage.dragSelection - ds.moveSelection(x, y) - } - static onSelectUp(stage: Stage) { stage.dragSelection.removeSelection() } diff --git a/src/stage/mouse-observer.ts b/src/stage/mouse-observer.ts index 673ecd586..84c216a01 100644 --- a/src/stage/mouse-observer.ts +++ b/src/stage/mouse-observer.ts @@ -286,8 +286,8 @@ class MouseObserver { this.signals.draggedXY.dispatch( this.prevPosition.x, this.prevPosition.y, - this.position.x, - this.position.y + this.canvasPosition.x, + this.canvasPosition.y ) } } @@ -320,9 +320,10 @@ class MouseObserver { if (event.target === this.domElement) { event.preventDefault() } - this.signals.dropped.dispatch(); + this._setKeys(event) const cp = this.canvasPosition + this.signals.dropped.dispatch(); if (this._distance() < 4) { this.lastClicked = window.performance.now() if (this.doubleClickPending && this.prevClickCP.distanceTo(cp) < 4) { diff --git a/src/viewer/viewer.ts b/src/viewer/viewer.ts index d3c99aae7..eb4fb373b 100644 --- a/src/viewer/viewer.ts +++ b/src/viewer/viewer.ts @@ -1007,14 +1007,16 @@ export default class Viewer { x1 *= window.devicePixelRatio y1 *= window.devicePixelRatio - let x = Math.max(x0 - 2, x1 - 2, 0) - let y = Math.min(y0 - 2, y1 - 2, 0) + let x = Math.min(x0, x1) + x = Math.max(x-2, 0) + let y = Math.min(this.pickingTarget.height-y0, this.pickingTarget.height-y1) + y = Math.max(y-2, 0) let px = Math.abs(x1 - x0) + 5 let py = Math.abs(y1 - y0) + 5 - console.log(x0, y0, x1, y1, x, y, px, py) + console.log(x0, y0, x1, y1, x, y, px, py, window.devicePixelRatio, this.pickingTarget) let _pixelBufferFloat = new Float32Array(4 * px * py) let _pixelBufferUint = new Uint8Array(4 * px * py) From a63c03b1063585493f437c0c090ceff5e264ea6b Mon Sep 17 00:00:00 2001 From: Lily Wang Date: Fri, 14 Jun 2019 16:45:38 +1000 Subject: [PATCH 08/16] current --- src/controls/mouse-actions.ts | 15 ++-- src/stage/mouse-observer.ts | 2 +- src/stage/selecting-behavior.ts | 18 ++-- src/structure/structure.ts | 144 ++++++++++++++++---------------- src/utils/toggle-set.ts | 2 - src/viewer/viewer.ts | 10 +-- 6 files changed, 94 insertions(+), 97 deletions(-) diff --git a/src/controls/mouse-actions.ts b/src/controls/mouse-actions.ts index 713f4bd33..9bda6b2b0 100644 --- a/src/controls/mouse-actions.ts +++ b/src/controls/mouse-actions.ts @@ -250,10 +250,12 @@ class MouseActions { } } - static selectPickAll(stage: Stage, pickingProxies: PickingProxy[], x: number, y: number) { + static selectPickAll(stage: Stage, pickingProxies: PickingProxy[]) { let components: StructureComponent[] = [] let picked: SimpleSet[] = [] + stage.dragSelection.removeSelection() + pickingProxies.forEach(function (pickingProxy) { if (pickingProxy && pickingProxy.atom) { let a = pickingProxy.atom.index @@ -269,11 +271,12 @@ class MouseActions { picked[j].add(a) } }) - console.log('picked', picked) for (var i = 0; i < components.length; i++) { - components[i].setSelectedIndices(picked[i].list) + components[i].selectedPickIndices(picked[i].list) } + } + static onDragXY(stage: Stage, x: number, y: number) { stage.dragSelection.moveSelection(x, y) } @@ -365,14 +368,14 @@ export const MouseActionPresets = { ['scroll-shift-ctrl', MouseActions.zoomFocusScroll], ['press-shift-left', MouseActions.onSelectDown], - ['drop-shift-left', MouseActions.onSelectUp], - ['drop-left', MouseActions.onSelectUp], + ['drop-shift-left', MouseActions.selectPickAll], + ['drop-left', MouseActions.selectPickAll], ['drag-left', MouseActions.rotateDrag], ['drag-right', MouseActions.panDrag], ['drag-ctrl-left', MouseActions.rotateSelectionDrag], ['drag-ctrl-right', MouseActions.moveComponentDrag], - ['dragXY-shift-left', MouseActions.selectPickAll], + ['dragXY-shift-left', MouseActions.onDragXY], ['drag-middle', MouseActions.zoomFocusDrag], ['clickPick-shift-left', MouseActions.selectPick], diff --git a/src/stage/mouse-observer.ts b/src/stage/mouse-observer.ts index 673ecd586..a9ae5b6d9 100644 --- a/src/stage/mouse-observer.ts +++ b/src/stage/mouse-observer.ts @@ -320,7 +320,7 @@ class MouseObserver { if (event.target === this.domElement) { event.preventDefault() } - this.signals.dropped.dispatch(); + this.signals.dropped.dispatch(event.clientX, event.clientY); this._setKeys(event) const cp = this.canvasPosition if (this._distance() < 4) { diff --git a/src/stage/selecting-behavior.ts b/src/stage/selecting-behavior.ts index e3d3c2a9a..b3cfa4521 100644 --- a/src/stage/selecting-behavior.ts +++ b/src/stage/selecting-behavior.ts @@ -36,24 +36,22 @@ class SelectingBehavior { this.controls.run('press', x, y) } - _onDrop() { - this.controls.run('drop') + _onDrop(x: number, y: number) { + if (this.stage.dragSelection.isDown) { + const x0 = this.stage.dragSelection.startPoint.x + const y0 = this.stage.dragSelection.startPoint.y + let pickedProxies = this.stage.pickingControls.pickAll(x0, y0, x, y) + this.controls.run('drop', pickedProxies) + } } _onDragXY(x1: number, y1: number) { // const sp = this.stage.getParameters() as any if (this.stage.dragSelection.isDown) { - const x0 = this.stage.dragSelection.startPoint.x - const y0 = this.stage.dragSelection.startPoint.y - let pickedProxies = this.stage.pickingControls.pickAll(x0, y0, x1, y1) - this.controls.run('dragXY', pickedProxies, x1, y1) + this.controls.run('dragXY', x1, y1) } } - // _onDoubleClick (x: number, y: number) { - // this.controls.run('doubleClick') - // } - dispose() { // this.mouse.signals.clicked.remove(this._onClick, this) this.mouse.signals.pressed.remove(this._onPress, this) diff --git a/src/structure/structure.ts b/src/structure/structure.ts index ebe1deb75..42be53806 100644 --- a/src/structure/structure.ts +++ b/src/structure/structure.ts @@ -129,7 +129,7 @@ export type StructureSignals = { /** * Structure */ -class Structure implements Structure{ +class Structure implements Structure { signals: StructureSignals = { refreshed: new Signal() } @@ -138,11 +138,11 @@ class Structure implements Structure{ * @param {String} name - structure name * @param {String} path - source path */ - constructor (name = '', path = '') { + constructor(name = '', path = '') { this.init(name, path) } - init (name: string, path: string) { + init(name: string, path: string) { this.name = name this.path = path this.title = '' @@ -191,9 +191,9 @@ class Structure implements Structure{ this._cp = this.getChainProxy() } - get type () { return 'Structure' } + get type() { return 'Structure' } - finalizeAtoms () { + finalizeAtoms() { this.atomSet = this.getAtomSet() this.atomCount = this.atomStore.count this.boundingBox = this.getBoundingBox(undefined, this.boundingBox) @@ -201,7 +201,7 @@ class Structure implements Structure{ this.spatialHash = new SpatialHash(this.atomStore, this.boundingBox) } - finalizeBonds () { + finalizeBonds() { this.bondSet = this.getBondSet() this.bondCount = this.bondStore.count this.bondHash = new BondHash(this.bondStore, this.atomStore.count) @@ -212,35 +212,35 @@ class Structure implements Structure{ } for (let name in this.atomSetDict) { - this.atomSetCache[ '__' + name ] = this.atomSetDict[ name ].clone() + this.atomSetCache['__' + name] = this.atomSetDict[name].clone() } } // - getBondProxy (index?: number) { + getBondProxy(index?: number) { return new BondProxy(this, index) } - getAtomProxy (index?: number) { + getAtomProxy(index?: number) { return new AtomProxy(this, index) } - getResidueProxy (index?: number) { + getResidueProxy(index?: number) { return new ResidueProxy(this, index) } - getChainProxy (index?: number) { + getChainProxy(index?: number) { return new ChainProxy(this, index) } - getModelProxy (index?: number) { + getModelProxy(index?: number) { return new ModelProxy(this, index) } // - getBondSet (/* selection */) { + getBondSet(/* selection */) { // TODO implement selection parameter const n = this.bondStore.count @@ -269,7 +269,7 @@ class Structure implements Structure{ return bondSet } - getBackboneBondSet (/* selection */) { + getBackboneBondSet(/* selection */) { // TODO implement selection parameter const n = this.backboneBondStore.count @@ -293,7 +293,7 @@ class Structure implements Structure{ return backboneBondSet } - getRungBondSet (/* selection */) { + getRungBondSet(/* selection */) { // TODO implement selection parameter const n = this.rungBondStore.count @@ -326,7 +326,7 @@ class Structure implements Structure{ * BitArray: return bit array * @return {BitArray} set of atoms */ - getAtomSet (selection?: boolean|Selection|BitArray) { + getAtomSet(selection?: boolean | Selection | BitArray) { const n = this.atomStore.count if (selection === undefined) { @@ -338,7 +338,7 @@ class Structure implements Structure{ } else if (selection && selection.test) { const seleString = selection.string if (seleString in this.atomSetCache) { - return this.atomSetCache[ seleString ] + return this.atomSetCache[seleString] } else { if (seleString === '') { return new BitArray(n, true) @@ -347,7 +347,7 @@ class Structure implements Structure{ this.eachAtom(function (ap: AtomProxy) { atomSet.set(ap.index) }, selection) - this.atomSetCache[ seleString ] = atomSet + this.atomSetCache[seleString] = atomSet return atomSet } } @@ -364,7 +364,7 @@ class Structure implements Structure{ * @param {Number} radius - radius to select within * @return {BitArray} set of atoms */ - getAtomSetWithinSelection (selection: boolean|Selection|BitArray, radius: number) { + getAtomSetWithinSelection(selection: boolean | Selection | BitArray, radius: number) { const spatialHash = this.spatialHash const atomSet = this.getAtomSet(false) const ap = this.getAtomProxy() @@ -387,7 +387,7 @@ class Structure implements Structure{ * @param {Number} radius - radius to select within * @return {BitArray} set of atoms */ - getAtomSetWithinPoint (point: Vector3|AtomProxy, radius: number) { + getAtomSetWithinPoint(point: Vector3 | AtomProxy, radius: number) { const p = point const atomSet = this.getAtomSet(false) @@ -409,7 +409,7 @@ class Structure implements Structure{ * @param {[type]} outside - use only values falling outside of the min/max values * @return {BitArray} set of atoms */ - getAtomSetWithinVolume (volume: Volume, radius: number, minValue: number, maxValue: number, outside: boolean) { + getAtomSetWithinVolume(volume: Volume, radius: number, minValue: number, maxValue: number, outside: boolean) { const fv = new FilteredVolume(volume, minValue, maxValue, outside) as any // TODO const dp = fv.getDataPosition() @@ -420,7 +420,7 @@ class Structure implements Structure{ if (!this.spatialHash) return atomSet for (let i = 0; i < n; i += 3) { - this.spatialHash.within(dp[ i ], dp[ i + 1 ], dp[ i + 2 ], r).forEach(function (idx) { + this.spatialHash.within(dp[i], dp[i + 1], dp[i + 2], r).forEach(function (idx) { atomSet.set(idx) }) } @@ -433,13 +433,13 @@ class Structure implements Structure{ * @param {Selection} selection - the selection object * @return {BitArray} set of atoms */ - getAtomSetWithinGroup (selection: boolean|Selection) { + getAtomSetWithinGroup(selection: boolean | Selection) { const atomResidueIndex = this.atomStore.residueIndex const atomSet = this.getAtomSet(false) const rp = this.getResidueProxy() this.getAtomSet(selection).forEach(function (idx) { - rp.index = atomResidueIndex[ idx ] + rp.index = atomResidueIndex[idx] for (let idx2 = rp.atomOffset; idx2 <= rp.atomEnd; ++idx2) { atomSet.set(idx2) } @@ -450,11 +450,11 @@ class Structure implements Structure{ // - getSelection (): false|Selection { + getSelection(): false | Selection { return false } - getStructure (): Structure|StructureView { + getStructure(): Structure | StructureView { return this } @@ -464,7 +464,7 @@ class Structure implements Structure{ * @param {EntityType} type - entity type * @return {undefined} */ - eachEntity (callback: (entity: Entity) => void, type: number) { + eachEntity(callback: (entity: Entity) => void, type: number) { this.entityList.forEach(function (entity) { if (type === undefined || entity.getEntityType() === type) { callback(entity) @@ -478,7 +478,7 @@ class Structure implements Structure{ * @param {Selection} [selection] - the selection * @return {undefined} */ - eachBond (callback: (entity: BondProxy) => void, selection?: Selection) { + eachBond(callback: (entity: BondProxy) => void, selection?: Selection) { const bp = this.getBondProxy() let bondSet @@ -509,7 +509,7 @@ class Structure implements Structure{ * @param {Selection} [selection] - the selection * @return {undefined} */ - eachAtom (callback: (entity: AtomProxy) => void, selection?: Selection) { + eachAtom(callback: (entity: AtomProxy) => void, selection?: Selection) { if (selection && selection.test) { this.eachModel(function (mp) { mp.eachAtom(callback, selection) @@ -530,7 +530,7 @@ class Structure implements Structure{ * @param {Selection} [selection] - the selection * @return {undefined} */ - eachResidue (callback: (entity: ResidueProxy) => void, selection?: Selection) { + eachResidue(callback: (entity: ResidueProxy) => void, selection?: Selection) { if (selection && selection.test) { const mn = this.modelStore.count const mp = this.getModelProxy() @@ -564,19 +564,19 @@ class Structure implements Structure{ * @param {function(residueList: ResidueProxy[])} callback - the callback * @return {undefined} */ - eachResidueN (n: number, callback: (...entityArray: ResidueProxy[]) => void) { + eachResidueN(n: number, callback: (...entityArray: ResidueProxy[]) => void) { const rn = this.residueStore.count if (rn < n) return const array: ResidueProxy[] = new Array(n) for (let i = 0; i < n; ++i) { - array[ i ] = this.getResidueProxy(i) + array[i] = this.getResidueProxy(i) } callback.apply(this, array) for (let j = n; j < rn; ++j) { for (let i = 0; i < n; ++i) { - array[ i ].index += 1 + array[i].index += 1 } callback.apply(this, array) } @@ -588,7 +588,7 @@ class Structure implements Structure{ * @param {Selection} [selection] - the selection * @return {undefined} */ - eachPolymer (callback: (entity: Polymer) => void, selection?: Selection) { + eachPolymer(callback: (entity: Polymer) => void, selection?: Selection) { if (selection && selection.modelOnlyTest) { const modelOnlyTest = selection.modelOnlyTest @@ -610,7 +610,7 @@ class Structure implements Structure{ * @param {Selection} [selection] - the selection * @return {undefined} */ - eachChain (callback: (entity: ChainProxy) => void, selection?: Selection) { + eachChain(callback: (entity: ChainProxy) => void, selection?: Selection) { if (selection && selection.test) { this.eachModel(function (mp) { mp.eachChain(callback, selection) @@ -631,7 +631,7 @@ class Structure implements Structure{ * @param {Selection} [selection] - the selection * @return {undefined} */ - eachModel (callback: (entity: ModelProxy) => void, selection?: Selection) { + eachModel(callback: (entity: ModelProxy) => void, selection?: Selection) { const n = this.modelStore.count const mp = this.getModelProxy() @@ -660,7 +660,7 @@ class Structure implements Structure{ // - getAtomData (params: AtomDataParams) { + getAtomData(params: AtomDataParams) { const p = Object.assign({}, params) if (p.colorParams) p.colorParams.structure = this.getStructure() @@ -692,7 +692,7 @@ class Structure implements Structure{ atomData.index = new Uint32Array(atomCount) } - const {position, color, picking, radius, index} = atomData + const { position, color, picking, radius, index } = atomData atomSet.forEach((idx: number, i: number) => { const i3 = i * 3 @@ -704,19 +704,19 @@ class Structure implements Structure{ colormaker.atomColorToArray(ap, color, i3) } if (picking) { - picking.array![ i ] = idx + picking.array![i] = idx } if (radius) { - radius[ i ] = radiusFactory.atomRadius(ap) + radius[i] = radiusFactory.atomRadius(ap) } if (index) { - index[ i ] = idx + index[i] = idx } }) return atomData } - getBondData (params: BondDataParams) { + getBondData(params: BondDataParams) { const p = Object.assign({}, params) if (p.colorParams) p.colorParams.structure = this.getStructure() @@ -742,7 +742,7 @@ class Structure implements Structure{ const storeBondOrder = bp.bondStore.bondOrder bondCount = 0 bondSet.forEach(function (index: number) { - bondCount += storeBondOrder[ index ] + bondCount += storeBondOrder[index] }) } else { bondCount = bondSet.getSize() @@ -770,7 +770,7 @@ class Structure implements Structure{ } } - const {position1, position2, color, color2, picking, radius, radius2} = bondData + const { position1, position2, color, color2, picking, radius, radius2 } = bondData let i = 0 let j, i3, k, bondOrder, absOffset @@ -856,28 +856,28 @@ class Structure implements Structure{ } } if (picking && picking.array) { - picking.array[ i ] = index + picking.array[i] = index if (isMulti && bondOrder > 1) { for (j = 1; j < bondOrder; ++j) { - picking.array[ i + j ] = index + picking.array[i + j] = index } } } if (radius) { - radius[ i ] = radiusFactory.atomRadius(ap1) + radius[i] = radiusFactory.atomRadius(ap1) if (isMulti && bondOrder > 1) { - multiRadius = radius[ i ] * bondScale / (isOffset ? 1 : (0.5 * bondOrder)) + multiRadius = radius[i] * bondScale / (isOffset ? 1 : (0.5 * bondOrder)) for (j = isOffset ? 1 : 0; j < bondOrder; ++j) { - radius[ i + j ] = multiRadius + radius[i + j] = multiRadius } } } if (radius2) { - radius2[ i ] = radiusFactory.atomRadius(ap2) + radius2[i] = radiusFactory.atomRadius(ap2) if (isMulti && bondOrder > 1) { - multiRadius = radius2[ i ] * bondScale / (isOffset ? 1 : (0.5 * bondOrder)) + multiRadius = radius2[i] * bondScale / (isOffset ? 1 : (0.5 * bondOrder)) for (j = isOffset ? 1 : 0; j < bondOrder; ++j) { - radius2[ i + j ] = multiRadius + radius2[i + j] = multiRadius } } } @@ -887,7 +887,7 @@ class Structure implements Structure{ return bondData } - getBackboneAtomData (params: AtomDataParams) { + getBackboneAtomData(params: AtomDataParams) { params = Object.assign({ atomSet: this.atomSetCache.__backbone }, params) @@ -895,7 +895,7 @@ class Structure implements Structure{ return this.getAtomData(params) } - getBackboneBondData (params: BondDataParams) { + getBackboneBondData(params: BondDataParams) { params = Object.assign({ bondSet: this.getBackboneBondSet(), bondStore: this.backboneBondStore @@ -904,7 +904,7 @@ class Structure implements Structure{ return this.getBondData(params) } - getRungAtomData (params: AtomDataParams) { + getRungAtomData(params: AtomDataParams) { params = Object.assign({ atomSet: this.atomSetCache.__rung }, params) @@ -912,7 +912,7 @@ class Structure implements Structure{ return this.getAtomData(params) } - getRungBondData (params: BondDataParams) { + getRungBondData(params: BondDataParams) { params = Object.assign({ bondSet: this.getRungBondSet(), bondStore: this.rungBondStore @@ -929,7 +929,7 @@ class Structure implements Structure{ * @param {Box3} [box] - optional target * @return {Vector3} the box */ - getBoundingBox (selection?: Selection, box?: Box3) { + getBoundingBox(selection?: Selection, box?: Box3) { if (Debug) Log.time('getBoundingBox') box = box || new Box3() @@ -969,7 +969,7 @@ class Structure implements Structure{ * @param {Selection} [selection] - the selection * @return {PrincipalAxes} the principal axes */ - getPrincipalAxes (selection?: Selection) { + getPrincipalAxes(selection?: Selection) { if (Debug) Log.time('getPrincipalAxes') let i = 0 @@ -977,9 +977,9 @@ class Structure implements Structure{ const cd = coords.data this.eachAtom(a => { - cd[ i + 0 ] = a.x - cd[ i + 1 ] = a.y - cd[ i + 2 ] = a.z + cd[i + 0] = a.x + cd[i + 1] = a.y + cd[i + 2] = a.z i += 3 }, selection) @@ -993,7 +993,7 @@ class Structure implements Structure{ * @param {Selection} [selection] - the selection * @return {Vector3} the center */ - atomCenter (selection?: Selection) { + atomCenter(selection?: Selection) { if (selection) { return this.getBoundingBox(selection).getCenter(new Vector3()) } else { @@ -1001,7 +1001,7 @@ class Structure implements Structure{ } } - hasCoords () { + hasCoords() { if (this._hasCoords === undefined) { const atomStore = this.atomStore this._hasCoords = ( @@ -1009,14 +1009,14 @@ class Structure implements Structure{ arrayMin(atomStore.y) !== 0 || arrayMax(atomStore.y) !== 0 || arrayMin(atomStore.z) !== 0 || arrayMax(atomStore.z) !== 0 ) || ( - // allow models with a single atom at the origin - atomStore.count / this.modelStore.count === 1 - ) + // allow models with a single atom at the origin + atomStore.count / this.modelStore.count === 1 + ) } return this._hasCoords; } - getSequence (selection?: Selection) { + getSequence(selection?: Selection) { const seq: string[] = [] const rp = this.getResidueProxy() @@ -1030,7 +1030,7 @@ class Structure implements Structure{ return seq } - getAtomIndices (selection?: Selection) { + getAtomIndices(selection?: Selection) { if (selection && selection.string) { const indices: number[] = [] this.eachAtom(function (ap: AtomProxy) { @@ -1048,7 +1048,7 @@ class Structure implements Structure{ * @param {Selection} selection - limit count to selection * @return {Integer} count */ - getChainnameCount (selection?: Selection) { + getChainnameCount(selection?: Selection) { const chainnames = new Set() this.eachChain(function (cp: ChainProxy) { if (cp.residueCount) { @@ -1061,7 +1061,7 @@ class Structure implements Structure{ // - updatePosition (position: Float32Array|number[]) { + updatePosition(position: Float32Array | number[]) { let i = 0 this.eachAtom(function (ap: AtomProxy) { @@ -1072,7 +1072,7 @@ class Structure implements Structure{ this._hasCoords = undefined // to trigger recalculation } - refreshPosition () { + refreshPosition() { this.getBoundingBox(undefined, this.boundingBox) this.boundingBox.getCenter(this.center) this.spatialHash = new SpatialHash(this.atomStore, this.boundingBox) @@ -1083,7 +1083,7 @@ class Structure implements Structure{ * Unsets properties to help garbage collection. * @return {undefined} */ - dispose () { + dispose() { if (this.frames) this.frames.length = 0 if (this.boxes) this.boxes.length = 0 diff --git a/src/utils/toggle-set.ts b/src/utils/toggle-set.ts index ce83f1c49..8b64a635f 100644 --- a/src/utils/toggle-set.ts +++ b/src/utils/toggle-set.ts @@ -40,7 +40,6 @@ export function createToggleSet(): ToggleSet { toggleAny: function (values: T[]) { let addAll = false; for (var i = 0; i < values.length; i++) { - console.log('toggle', list, values[i], addAll, list.includes(values[i])) if (!list.includes(values[i])) { addAll = true; } @@ -54,7 +53,6 @@ export function createToggleSet(): ToggleSet { } } } else { - console.log('deleting') for (var i = 0; i < values.length; i++) { let value = values[i] if (list.indexOf(value) !== -1) { diff --git a/src/viewer/viewer.ts b/src/viewer/viewer.ts index d3c99aae7..ba0ceefb5 100644 --- a/src/viewer/viewer.ts +++ b/src/viewer/viewer.ts @@ -1007,14 +1007,12 @@ export default class Viewer { x1 *= window.devicePixelRatio y1 *= window.devicePixelRatio - let x = Math.max(x0 - 2, x1 - 2, 0) - let y = Math.min(y0 - 2, y1 - 2, 0) + let x = Math.min(x0, x1) + let y = this.pickingTarget.height - Math.min(y0, y1) - let px = Math.abs(x1 - x0) + 5 - let py = Math.abs(y1 - y0) + 5 - - console.log(x0, y0, x1, y1, x, y, px, py) + let px = Math.abs(x1 - x0) + let py = Math.abs(y1 - y0) let _pixelBufferFloat = new Float32Array(4 * px * py) let _pixelBufferUint = new Uint8Array(4 * px * py) From 4a70f4bb45dc895262b4fa423df4c53e06d3603a Mon Sep 17 00:00:00 2001 From: Lily Wang Date: Tue, 18 Jun 2019 10:55:13 +1000 Subject: [PATCH 09/16] started itp-parser --- src/parser/itp-parser.ts | 192 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 src/parser/itp-parser.ts diff --git a/src/parser/itp-parser.ts b/src/parser/itp-parser.ts new file mode 100644 index 000000000..7f8333c30 --- /dev/null +++ b/src/parser/itp-parser.ts @@ -0,0 +1,192 @@ +/** + * @file Top Parser + * @author Alexander Rose + * @private + */ + +import { Debug, Log, ParserRegistry } from '../globals' +import StructureParser from './structure-parser' +import { WaterNames } from '../structure/structure-constants' +import { + assignResidueTypeBonds, calculateBondsBetween, + calculateBondsWithin, getChainname +} from '../structure/structure-utils' + +const enum Mode { + System, + Molecules, + Moleculetype, + Atoms, + Bonds +} + +const reField = /\[ (.+) \]/ +const reWhitespace = /\s+/ + +class TopParser extends StructureParser { + get type () { return 'top' } + + _parse () { + // http://manual.gromacs.org/online/top.html + + if (Debug) Log.time('TopParser._parse ' + this.name) + + const s = this.structure + const sb = this.structureBuilder + + // + + const atomMap = s.atomMap + const bondStore = s.bondStore + + const atomStore = s.atomStore + atomStore.addField('partialCharge', 1, 'float32') + + const molecules: [string, number][] = [] + const moleculetypeDict: {[k: string]: {atoms: any[], bonds: any[] }} = {} + + let currentMoleculetype: { + atoms: [number, string, string, number][], + bonds: [number, number][] + } + let mode: number|undefined + + function _parseChunkOfLines (_i: number, _n: number, lines: string[]) { + for (let i = _i; i < _n; ++i) { + const line = lines[ i ] + let lt = line.trim() + + if (!lt || lt[0] === '*' || lt[0] === ';') { + continue + } + + if (lt.startsWith('#include')) { + throw new Error('TopParser: #include statements not allowed') + } + + const fieldMatch = line.match(reField) + if (fieldMatch !== null) { + const name = fieldMatch[1] + if (name === 'moleculetype') { + mode = Mode.Moleculetype + currentMoleculetype = { + atoms: [], + bonds: [] + } + } else if (name === 'atoms') { + mode = Mode.Atoms + } else if (name === 'bonds') { + mode = Mode.Bonds + } else if (name === 'system') { + mode = Mode.System + } else if (name === 'molecules') { + mode = Mode.Molecules + } else { + mode = undefined + } + continue + } + + const cIdx = lt.indexOf(';') + if (cIdx !== -1) { + lt = lt.substring(0, cIdx).trim() + } + if (mode === Mode.Moleculetype) { + const molName = lt.split(reWhitespace)[0] + moleculetypeDict[molName] = currentMoleculetype + } else if (mode === Mode.Atoms) { + const ls = lt.split(reWhitespace) + currentMoleculetype.atoms.push([ + parseInt(ls[2]), // resnr + ls[3], // residue + ls[4], // atom + parseFloat(ls[6]) // charge + ]) + } else if (mode === Mode.Bonds) { + const ls = lt.split(reWhitespace) + currentMoleculetype.bonds.push([ + parseInt(ls[0]), // ai + parseInt(ls[1]) // aj + ]) + } else if (mode === Mode.System) { + s.title = lt + } else if (mode === Mode.Molecules) { + const ls = lt.split(reWhitespace) + molecules.push([ + ls[0], // name + parseInt(ls[1]) // count + ]) + } + } + } + + this.streamer.eachChunkOfLines(function (lines/*, chunkNo, chunkCount */) { + _parseChunkOfLines(0, lines.length, lines) + }) + + let atomCount = 0 + let bondCount = 0 + molecules.forEach(function (val) { + const [name, molCount] = val + const molType = moleculetypeDict[name] + atomCount += molCount * molType.atoms.length + bondCount += molCount * molType.bonds.length + }) + + atomStore.resize(atomCount) + bondStore.resize(bondCount) + + let atomIdx = 0 + let resIdx = 0 + let chainidIdx = 0 + let chainnameIdx = 0 + let bondIdx = 0 + let atomOffset = 0 + let lastResno: number + + molecules.forEach(function (val) { + const [name, molCount] = val + const molType = moleculetypeDict[name] + const chainname = getChainname(chainnameIdx) + for (let i = 0; i < molCount; ++i) { + lastResno = -1 + const chainid = WaterNames.includes(name) ? chainname : getChainname(chainidIdx) + molType.atoms.forEach(function (atomData) { + const [resno, resname, atomname, charge] = atomData + if (resno !== lastResno) { + ++resIdx + } + atomStore.atomTypeId[atomIdx] = atomMap.add(atomname) + atomStore.serial[atomIdx] = atomIdx + 1 + atomStore.partialCharge[atomIdx] = charge + sb.addAtom(0, chainname, chainid, resname, resIdx + 1) + ++atomIdx + lastResno = resno + }) + molType.bonds.forEach(function (bondData) { + bondStore.atomIndex1[bondIdx] = atomOffset + bondData[0] - 1 + bondStore.atomIndex2[bondIdx] = atomOffset + bondData[1] - 1 + ++bondIdx + }) + ++chainidIdx + atomOffset += molType.atoms.length + } + ++chainnameIdx + }) + + bondStore.count = bondCount + + sb.finalize() + s.finalizeAtoms() + s.finalizeBonds() + calculateBondsWithin(s, true) + calculateBondsBetween(s, true, true) + assignResidueTypeBonds(s) + + if (Debug) Log.timeEnd('TopParser._parse ' + this.name) + } +} + +ParserRegistry.add('top', TopParser) + +export default TopParser From 07da327b50788139223adcf6a2403021d7cf79dd Mon Sep 17 00:00:00 2001 From: Lily Wang Date: Tue, 18 Jun 2019 13:59:19 +1000 Subject: [PATCH 10/16] added drag and selection --- examples/examples/annotations.html | 57 + examples/examples/css/dark.css | 69 + examples/examples/css/font-awesome.min.css | 4 + examples/examples/css/light.css | 69 + examples/examples/css/main.css | 454 ++++ examples/examples/embedded.html | 19 + examples/examples/fonts/FontAwesome.otf | Bin 0 -> 75188 bytes .../examples/fonts/fontawesome-webfont.eot | Bin 0 -> 72449 bytes .../examples/fonts/fontawesome-webfont.svg | 504 ++++ .../examples/fonts/fontawesome-webfont.ttf | Bin 0 -> 141564 bytes .../examples/fonts/fontawesome-webfont.woff | Bin 0 -> 83760 bytes examples/examples/grid.html | 149 + examples/examples/js/gui.js | 2394 +++++++++++++++++ examples/examples/js/lib/colorpicker.min.js | 14 + examples/examples/js/lib/signals.min.js | 14 + examples/examples/js/lib/tether.min.js | 3 + examples/examples/js/ui/ui.extra.js | 1136 ++++++++ examples/examples/js/ui/ui.js | 1037 +++++++ examples/examples/js/ui/ui.ngl.js | 368 +++ examples/examples/mobile.html | 56 + examples/examples/parallel.html | 33 + examples/examples/scripts/color/atomindex.js | 5 + examples/examples/scripts/color/bfactor.js | 5 + examples/examples/scripts/color/chainid.js | 5 + examples/examples/scripts/color/custom.js | 17 + .../examples/scripts/color/electrostatic.js | 9 + examples/examples/scripts/color/element.js | 5 + examples/examples/scripts/color/modelindex.js | 5 + .../examples/scripts/color/partialcharge.js | 5 + examples/examples/scripts/color/resname.js | 7 + examples/examples/scripts/color/selection.js | 25 + examples/examples/scripts/color/sstruc.js | 5 + examples/examples/scripts/color/volume-esp.js | 25 + examples/examples/scripts/color/volume.js | 27 + .../examples/scripts/component/getByName.js | 12 + examples/examples/scripts/component/matrix.js | 15 + .../scripts/component/shape-buffer.js | 19 + .../examples/scripts/component/shape-cat.js | 32 + .../scripts/component/shape-wireframe.js | 8 + examples/examples/scripts/component/shape.js | 23 + .../component/structure-autoChainName.js | 8 + .../scripts/component/structure-biomol.js | 12 + .../component/structure-biomolSimple.js | 11 + .../scripts/component/structure-bondOrders.js | 5 + .../component/structure-coarseGrained.js | 7 + .../scripts/component/structure-cyclic.js | 7 + .../scripts/component/structure-dna.js | 14 + .../scripts/component/structure-multiModel.js | 15 + .../scripts/component/structure-superpose.js | 25 + .../examples/scripts/component/transform.js | 21 + .../scripts/interactive/annotation.js | 31 + .../scripts/interactive/crosslinking.js | 884 ++++++ .../scripts/interactive/hover-tooltip.js | 34 + .../scripts/interactive/interpolate.js | 20 + .../scripts/interactive/ligand-viewer.js | 627 +++++ .../scripts/interactive/simple-viewer.js | 125 + .../scripts/interactive/xray-viewer.js | 455 ++++ examples/examples/scripts/parser/brix.js | 10 + examples/examples/scripts/parser/ccp4.js | 48 + .../examples/scripts/parser/cif-chemComp.js | 5 + examples/examples/scripts/parser/cif-core.js | 14 + examples/examples/scripts/parser/cif.js | 5 + examples/examples/scripts/parser/cns.js | 12 + .../examples/scripts/parser/cube-benzene.js | 25 + examples/examples/scripts/parser/cube-big.js | 21 + .../scripts/parser/cube-bromobenzene.js | 10 + .../examples/scripts/parser/cube-protein.js | 7 + examples/examples/scripts/parser/cube.js | 12 + examples/examples/scripts/parser/dcd-large.js | 20 + examples/examples/scripts/parser/dcd.js | 20 + examples/examples/scripts/parser/dsn6.js | 10 + examples/examples/scripts/parser/dx.js | 26 + examples/examples/scripts/parser/dxbin.js | 51 + examples/examples/scripts/parser/gro-large.js | 5 + .../examples/scripts/parser/gro-trajectory.js | 13 + examples/examples/scripts/parser/gro.js | 6 + examples/examples/scripts/parser/kin.js | 47 + examples/examples/scripts/parser/map.js | 13 + .../examples/scripts/parser/mmtf-reduced.js | 2 + examples/examples/scripts/parser/mmtf.js | 6 + examples/examples/scripts/parser/mol2.js | 5 + examples/examples/scripts/parser/mrc.js | 2 + examples/examples/scripts/parser/nctraj.js | 9 + examples/examples/scripts/parser/obj.js | 11 + examples/examples/scripts/parser/pdb.js | 5 + examples/examples/scripts/parser/pdbqt.js | 9 + examples/examples/scripts/parser/ply.js | 12 + .../scripts/parser/pqr-explicit-radii.js | 16 + examples/examples/scripts/parser/pqr.js | 9 + examples/examples/scripts/parser/prmtop.js | 14 + examples/examples/scripts/parser/psf.js | 12 + .../examples/scripts/parser/sdf-models.js | 33 + examples/examples/scripts/parser/sdf.js | 5 + examples/examples/scripts/parser/top.js | 15 + examples/examples/scripts/parser/trr.js | 9 + .../examples/scripts/parser/validation.js | 18 + examples/examples/scripts/parser/xtc.js | 9 + .../examples/scripts/representation/angle.js | 16 + .../examples/scripts/representation/axes.js | 16 + .../scripts/representation/ball+stick.js | 5 + .../scripts/representation/contact.js | 71 + .../scripts/representation/dihedral.js | 21 + .../scripts/representation/distance.js | 16 + .../scripts/representation/helixorient.js | 13 + .../scripts/representation/hyperball.js | 6 + .../examples/scripts/representation/label.js | 19 + .../scripts/representation/licorice.js | 5 + .../scripts/representation/line-and-cross.js | 8 + .../examples/scripts/representation/line.js | 16 + .../representation/molecularsurface-av.js | 31 + .../representation/molecularsurface-filter.js | 43 + .../representation/molecularsurface.js | 14 + .../examples/scripts/representation/point.js | 16 + .../representation/representation-lazy.js | 6 + .../examples/scripts/representation/rocket.js | 6 + .../examples/scripts/representation/slice.js | 19 + .../scripts/representation/spacefill.js | 5 + .../examples/scripts/representation/trace.js | 5 + .../scripts/representation/tube-bfactor.js | 19 + .../scripts/representation/unitcell.js | 9 + .../examples/scripts/selection/aromatic.js | 8 + examples/examples/scripts/selection/basic.js | 8 + examples/examples/scripts/selection/bonded.js | 12 + .../examples/scripts/selection/component.js | 14 + examples/examples/scripts/selection/large.js | 27 + examples/examples/scripts/selection/ring.js | 10 + .../examples/scripts/selection/spatialHash.js | 38 + examples/examples/scripts/selection/sstruc.js | 9 + .../scripts/showcase/chlorellaVirus.js | 14 + .../scripts/showcase/electrostatic-apbs.js | 50 + .../examples/scripts/showcase/ferredoxin.js | 48 + .../examples/scripts/showcase/ferritin.js | 37 + examples/examples/scripts/showcase/gfp.js | 32 + examples/examples/scripts/showcase/hiv.js | 104 + .../examples/scripts/showcase/norovirus.js | 33 + examples/examples/scripts/showcase/qmean.js | 79 + .../examples/scripts/showcase/rhodopsin.js | 40 + .../examples/scripts/showcase/ribosome.js | 44 + examples/examples/scripts/showcase/viruses.js | 80 + examples/examples/scripts/test/1blu.js | 15 + examples/examples/scripts/test/2buk.js | 8 + examples/examples/scripts/test/alignment.js | 26 + examples/examples/scripts/test/alignment2.js | 22 + .../scripts/test/backboneTypeChange.js | 8 + examples/examples/scripts/test/concat.js | 28 + .../examples/scripts/test/dashedCylinders.js | 28 + examples/examples/scripts/test/explode.js | 56 + .../scripts/test/helixorient_issue-7.js | 12 + examples/examples/scripts/test/impostor.js | 6 + examples/examples/scripts/test/inter-bonds.js | 5 + examples/examples/scripts/test/map-shift.js | 35 + .../examples/scripts/test/molsurf-object.js | 12 + examples/examples/scripts/test/nci.js | 473 ++++ examples/examples/scripts/test/orient.js | 12 + examples/examples/scripts/test/pbc.js | 9 + .../examples/scripts/test/pdbDaminoacids.js | 14 + .../scripts/test/pdbModifiedResidue.js | 12 + .../examples/scripts/test/pickingImage.js | 19 + .../examples/scripts/test/superposition.js | 18 + examples/examples/scripts/test/timing.js | 18 + examples/examples/scripts/test/xray.js | 42 + examples/examples/test.html | 34 + examples/examples/webapp.html | 64 + src/controls/mouse-actions.ts | 113 +- 164 files changed, 11626 insertions(+), 51 deletions(-) create mode 100644 examples/examples/annotations.html create mode 100644 examples/examples/css/dark.css create mode 100644 examples/examples/css/font-awesome.min.css create mode 100644 examples/examples/css/light.css create mode 100644 examples/examples/css/main.css create mode 100644 examples/examples/embedded.html create mode 100644 examples/examples/fonts/FontAwesome.otf create mode 100644 examples/examples/fonts/fontawesome-webfont.eot create mode 100644 examples/examples/fonts/fontawesome-webfont.svg create mode 100644 examples/examples/fonts/fontawesome-webfont.ttf create mode 100644 examples/examples/fonts/fontawesome-webfont.woff create mode 100644 examples/examples/grid.html create mode 100644 examples/examples/js/gui.js create mode 100644 examples/examples/js/lib/colorpicker.min.js create mode 100644 examples/examples/js/lib/signals.min.js create mode 100644 examples/examples/js/lib/tether.min.js create mode 100644 examples/examples/js/ui/ui.extra.js create mode 100644 examples/examples/js/ui/ui.js create mode 100644 examples/examples/js/ui/ui.ngl.js create mode 100644 examples/examples/mobile.html create mode 100644 examples/examples/parallel.html create mode 100644 examples/examples/scripts/color/atomindex.js create mode 100644 examples/examples/scripts/color/bfactor.js create mode 100644 examples/examples/scripts/color/chainid.js create mode 100644 examples/examples/scripts/color/custom.js create mode 100644 examples/examples/scripts/color/electrostatic.js create mode 100644 examples/examples/scripts/color/element.js create mode 100644 examples/examples/scripts/color/modelindex.js create mode 100644 examples/examples/scripts/color/partialcharge.js create mode 100644 examples/examples/scripts/color/resname.js create mode 100644 examples/examples/scripts/color/selection.js create mode 100644 examples/examples/scripts/color/sstruc.js create mode 100644 examples/examples/scripts/color/volume-esp.js create mode 100644 examples/examples/scripts/color/volume.js create mode 100644 examples/examples/scripts/component/getByName.js create mode 100644 examples/examples/scripts/component/matrix.js create mode 100644 examples/examples/scripts/component/shape-buffer.js create mode 100644 examples/examples/scripts/component/shape-cat.js create mode 100644 examples/examples/scripts/component/shape-wireframe.js create mode 100644 examples/examples/scripts/component/shape.js create mode 100644 examples/examples/scripts/component/structure-autoChainName.js create mode 100644 examples/examples/scripts/component/structure-biomol.js create mode 100644 examples/examples/scripts/component/structure-biomolSimple.js create mode 100644 examples/examples/scripts/component/structure-bondOrders.js create mode 100644 examples/examples/scripts/component/structure-coarseGrained.js create mode 100644 examples/examples/scripts/component/structure-cyclic.js create mode 100644 examples/examples/scripts/component/structure-dna.js create mode 100644 examples/examples/scripts/component/structure-multiModel.js create mode 100644 examples/examples/scripts/component/structure-superpose.js create mode 100644 examples/examples/scripts/component/transform.js create mode 100644 examples/examples/scripts/interactive/annotation.js create mode 100644 examples/examples/scripts/interactive/crosslinking.js create mode 100644 examples/examples/scripts/interactive/hover-tooltip.js create mode 100644 examples/examples/scripts/interactive/interpolate.js create mode 100644 examples/examples/scripts/interactive/ligand-viewer.js create mode 100644 examples/examples/scripts/interactive/simple-viewer.js create mode 100644 examples/examples/scripts/interactive/xray-viewer.js create mode 100644 examples/examples/scripts/parser/brix.js create mode 100644 examples/examples/scripts/parser/ccp4.js create mode 100644 examples/examples/scripts/parser/cif-chemComp.js create mode 100644 examples/examples/scripts/parser/cif-core.js create mode 100644 examples/examples/scripts/parser/cif.js create mode 100644 examples/examples/scripts/parser/cns.js create mode 100644 examples/examples/scripts/parser/cube-benzene.js create mode 100644 examples/examples/scripts/parser/cube-big.js create mode 100644 examples/examples/scripts/parser/cube-bromobenzene.js create mode 100644 examples/examples/scripts/parser/cube-protein.js create mode 100644 examples/examples/scripts/parser/cube.js create mode 100644 examples/examples/scripts/parser/dcd-large.js create mode 100644 examples/examples/scripts/parser/dcd.js create mode 100644 examples/examples/scripts/parser/dsn6.js create mode 100644 examples/examples/scripts/parser/dx.js create mode 100644 examples/examples/scripts/parser/dxbin.js create mode 100644 examples/examples/scripts/parser/gro-large.js create mode 100644 examples/examples/scripts/parser/gro-trajectory.js create mode 100644 examples/examples/scripts/parser/gro.js create mode 100644 examples/examples/scripts/parser/kin.js create mode 100644 examples/examples/scripts/parser/map.js create mode 100644 examples/examples/scripts/parser/mmtf-reduced.js create mode 100644 examples/examples/scripts/parser/mmtf.js create mode 100644 examples/examples/scripts/parser/mol2.js create mode 100644 examples/examples/scripts/parser/mrc.js create mode 100644 examples/examples/scripts/parser/nctraj.js create mode 100644 examples/examples/scripts/parser/obj.js create mode 100644 examples/examples/scripts/parser/pdb.js create mode 100644 examples/examples/scripts/parser/pdbqt.js create mode 100644 examples/examples/scripts/parser/ply.js create mode 100644 examples/examples/scripts/parser/pqr-explicit-radii.js create mode 100644 examples/examples/scripts/parser/pqr.js create mode 100644 examples/examples/scripts/parser/prmtop.js create mode 100644 examples/examples/scripts/parser/psf.js create mode 100644 examples/examples/scripts/parser/sdf-models.js create mode 100644 examples/examples/scripts/parser/sdf.js create mode 100644 examples/examples/scripts/parser/top.js create mode 100644 examples/examples/scripts/parser/trr.js create mode 100644 examples/examples/scripts/parser/validation.js create mode 100644 examples/examples/scripts/parser/xtc.js create mode 100644 examples/examples/scripts/representation/angle.js create mode 100644 examples/examples/scripts/representation/axes.js create mode 100644 examples/examples/scripts/representation/ball+stick.js create mode 100644 examples/examples/scripts/representation/contact.js create mode 100644 examples/examples/scripts/representation/dihedral.js create mode 100644 examples/examples/scripts/representation/distance.js create mode 100644 examples/examples/scripts/representation/helixorient.js create mode 100644 examples/examples/scripts/representation/hyperball.js create mode 100644 examples/examples/scripts/representation/label.js create mode 100644 examples/examples/scripts/representation/licorice.js create mode 100644 examples/examples/scripts/representation/line-and-cross.js create mode 100644 examples/examples/scripts/representation/line.js create mode 100644 examples/examples/scripts/representation/molecularsurface-av.js create mode 100644 examples/examples/scripts/representation/molecularsurface-filter.js create mode 100644 examples/examples/scripts/representation/molecularsurface.js create mode 100644 examples/examples/scripts/representation/point.js create mode 100644 examples/examples/scripts/representation/representation-lazy.js create mode 100644 examples/examples/scripts/representation/rocket.js create mode 100644 examples/examples/scripts/representation/slice.js create mode 100644 examples/examples/scripts/representation/spacefill.js create mode 100644 examples/examples/scripts/representation/trace.js create mode 100644 examples/examples/scripts/representation/tube-bfactor.js create mode 100644 examples/examples/scripts/representation/unitcell.js create mode 100644 examples/examples/scripts/selection/aromatic.js create mode 100644 examples/examples/scripts/selection/basic.js create mode 100644 examples/examples/scripts/selection/bonded.js create mode 100644 examples/examples/scripts/selection/component.js create mode 100644 examples/examples/scripts/selection/large.js create mode 100644 examples/examples/scripts/selection/ring.js create mode 100644 examples/examples/scripts/selection/spatialHash.js create mode 100644 examples/examples/scripts/selection/sstruc.js create mode 100644 examples/examples/scripts/showcase/chlorellaVirus.js create mode 100644 examples/examples/scripts/showcase/electrostatic-apbs.js create mode 100644 examples/examples/scripts/showcase/ferredoxin.js create mode 100644 examples/examples/scripts/showcase/ferritin.js create mode 100644 examples/examples/scripts/showcase/gfp.js create mode 100644 examples/examples/scripts/showcase/hiv.js create mode 100644 examples/examples/scripts/showcase/norovirus.js create mode 100644 examples/examples/scripts/showcase/qmean.js create mode 100644 examples/examples/scripts/showcase/rhodopsin.js create mode 100644 examples/examples/scripts/showcase/ribosome.js create mode 100644 examples/examples/scripts/showcase/viruses.js create mode 100644 examples/examples/scripts/test/1blu.js create mode 100644 examples/examples/scripts/test/2buk.js create mode 100644 examples/examples/scripts/test/alignment.js create mode 100644 examples/examples/scripts/test/alignment2.js create mode 100644 examples/examples/scripts/test/backboneTypeChange.js create mode 100644 examples/examples/scripts/test/concat.js create mode 100644 examples/examples/scripts/test/dashedCylinders.js create mode 100644 examples/examples/scripts/test/explode.js create mode 100644 examples/examples/scripts/test/helixorient_issue-7.js create mode 100644 examples/examples/scripts/test/impostor.js create mode 100644 examples/examples/scripts/test/inter-bonds.js create mode 100644 examples/examples/scripts/test/map-shift.js create mode 100644 examples/examples/scripts/test/molsurf-object.js create mode 100644 examples/examples/scripts/test/nci.js create mode 100644 examples/examples/scripts/test/orient.js create mode 100644 examples/examples/scripts/test/pbc.js create mode 100644 examples/examples/scripts/test/pdbDaminoacids.js create mode 100644 examples/examples/scripts/test/pdbModifiedResidue.js create mode 100644 examples/examples/scripts/test/pickingImage.js create mode 100644 examples/examples/scripts/test/superposition.js create mode 100644 examples/examples/scripts/test/timing.js create mode 100644 examples/examples/scripts/test/xray.js create mode 100644 examples/examples/test.html create mode 100644 examples/examples/webapp.html diff --git a/examples/examples/annotations.html b/examples/examples/annotations.html new file mode 100644 index 000000000..aa0c4425f --- /dev/null +++ b/examples/examples/annotations.html @@ -0,0 +1,57 @@ + + + + NGL - test + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/examples/css/dark.css b/examples/examples/css/dark.css new file mode 100644 index 000000000..f79e854c0 --- /dev/null +++ b/examples/examples/css/dark.css @@ -0,0 +1,69 @@ + +/* text color */ + +* { + color: #B8B8B8; +} + +input, +textarea, +button, +select, +option { + color: #111111; +} + +input[type=range]:focus:after { + color: #B8B8B8; +} + +a{ + color: #719eff; +} + +input.Number, input.File { + color: #A1B56C; +} + + +/* background color */ + +.OverlayPanel, +#menubar, +#menubar .menu .options, +#sidebar, +#toolbar +{ + background-color: #1C1F26; +} + + +/* border color */ + +.OverlayPanel, +#menubar .menu .options hr, +#sidebar > .Panel, +#sidebar > .Content > .Panel { + border-color: #444444; +} + + +/* special */ + +#menubar .menu .options .option:hover, +.option:hover > .Icon, +.option:hover > .Text { + color: #181818; + background-color: #7CAFC2; +} + +.highlight, +.highlight > .Icon, +.highlight > .Text { + color: #181818; + background-color: #7CAFC2; +} + +.EllipsisMultilineText:after { + background: linear-gradient(to right, rgba(0, 0, 0, 0), #1C1F26 50%, #1C1F26); +} diff --git a/examples/examples/css/font-awesome.min.css b/examples/examples/css/font-awesome.min.css new file mode 100644 index 000000000..3d920fc87 --- /dev/null +++ b/examples/examples/css/font-awesome.min.css @@ -0,0 +1,4 @@ +/*! + * Font Awesome 4.1.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.1.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.1.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.1.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.1.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-square:before,.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"} \ No newline at end of file diff --git a/examples/examples/css/light.css b/examples/examples/css/light.css new file mode 100644 index 000000000..d08e750d6 --- /dev/null +++ b/examples/examples/css/light.css @@ -0,0 +1,69 @@ + +/* text color */ + +* { + color: #555555; +} + +input, +textarea, +button, +select, +option { + color: #111111; +} + +input[type=range]:focus:after { + color: #555555; +} + +a{ + color: #1956d8; +} + +input.Number, input.File { + color: #79952e; +} + + +/* background color */ + +.OverlayPanel, +#menubar, +#menubar .menu .options, +#sidebar, +#toolbar +{ + background-color: #e1e4eb; +} + + +/* border color */ + +.OverlayPanel, +#menubar .menu .options hr, +#sidebar > .Panel, +#sidebar > .Content > .Panel { + border-color: #cccccc; +} + + +/* special */ + +#menubar .menu .options .option:hover, +.option:hover > .Icon, +.option:hover > .Text { + color: #D8D8D8; + background-color: #345a69; +} + +.highlight, +.highlight > .Icon, +.highlight > .Text { + color: #D8D8D8; + background-color: #345a69; +} + +.EllipsisMultilineText:after { + background: linear-gradient(to right, rgba(255, 255, 255, 0), #e1e4eb 50%, #e1e4eb); +} diff --git a/examples/examples/css/main.css b/examples/examples/css/main.css new file mode 100644 index 000000000..fa4e3309f --- /dev/null +++ b/examples/examples/css/main.css @@ -0,0 +1,454 @@ + +* { + vertical-align: middle; +} + +/* Webkit micro scrollbars */ + +::-webkit-scrollbar { + width:9px; + height:9px; +} + +::-webkit-scrollbar-track { + -webkit-border-radius:5px; + border-radius:5px; + background:rgba(140,140,140,0.1); +} + +::-webkit-scrollbar-thumb { + -webkit-border-radius:5px; + border-radius:5px; + background:rgba(140,140,140,0.2); +} + +::-webkit-scrollbar-thumb:hover { + background:rgba(140,140,140,0.4); +} + +::-webkit-scrollbar-thumb:window-inactive { + background:rgba(140,140,140,0.5); +} + +/* elmement */ + +body { + font-family: Arial, sans-serif; + font-size: 14px; + margin: 0; + overflow: hidden; +} + +hr { + border: 0px; + border-top: 1px solid #ccc; +} + +button { + position: relative; + margin-left: 0px; +} + +select { + margin-left: 1px; +} + +textarea { + white-space: pre; + word-wrap: normal; +} + + textarea.success { + border-color: #8b8 !important; + } + + textarea.fail { + border-color: #f00 !important; + background-color: rgba(255,0,0,0.05); + } + +textarea, input { outline: none; } /* osx */ + +input.Number { + font-size: 12px; /** TODO: Use of !imporant is not ideal **/ + background-color: transparent!important; /* For now this is a quick fix a rendering issue due to inherited background */ + border: 1px solid transparent; + padding: 2px; + cursor: col-resize; +} + +input.File { + border: 0px solid !important; + padding: 0px !important; +} + +input[type=range]:focus:after { + position: absolute; + transform: translate(-100%,-50% ); + content: attr(value); + font-size: 12px; +} + +/* class */ + +.deleteInfo:after { + position: absolute; + transform: translate(-50%,-250% ); + content: "double-click to delete"; + font-size: 10px; + display: block; +} + +.Panel { + + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + + /* No support for these yet */ + -o-user-select: none; + user-select: none; +} + +.OverlayPanel { + z-index: 10; + position: absolute; + padding: 10px; + overflow: auto; + border: 1px solid; +} + +.OverlayPanel:focus { + z-index: 20; +} + +.Text { + cursor: default; +} + +.FancySelect { + padding: 0; + cursor: default; + overflow: auto; + outline: none; +} + + .FancySelect .option { + padding: 4px; + white-space: nowrap; + } + +.CollapsiblePanel .CollapsiblePanelButton { + float: left; + margin-right: 6px; + width: 0px; + height: 0px; + border: 6px solid transparent; +} + +.CollapsiblePanel.collapsed > .CollapsiblePanelButton { + margin-top: 2px; + border-left-color: #555; +} + +.CollapsiblePanel:not(.collapsed) > .CollapsiblePanelButton { + margin-top: 6px; + border-top-color: #555; +} + +.CollapsiblePanel.collapsed .CollapsibleContent { + display: none; +} + +.CollapsiblePanel:not(.collapsed) > .CollapsibleContent { + clear: both; +} + +/* http://www.brianchu.com/blog/2013/11/02/creating-an-auto-growing-text-input/ */ + +.AdaptiveTextAreaContainer { + position: relative; + display: inline-block; + margin-top: 2px; + margin-bottom: 2px; +} + +.AdaptiveTextArea, .AdaptiveTextAreaSize { + min-height: 21px; + /* need to manually set font and font size */ + font-family: Arial, sans-serif; + font-size: 13px; + box-sizing: border-box; + padding: 2px; + border: 1px solid #ccc; + + overflow: hidden; + width: 100%; +} + +.AdaptiveTextArea { + height: 100%; + position: absolute; + resize: none; + + /* + "pre" or "preline" or "normal" fixes Chrome issue where + whitespace at end of lines does not trigger a line break. + However, it causes the text to exhibit the behavior seen with + "pre" that is described below. + */ + white-space: normal; + word-wrap: break-word; + overflow-wrap: break-word; +} + +.AdaptiveTextAreaSize { + visibility: hidden; + + /* + Pre-wrap: preserve spacing and newlines, but wrap text. + Pre: preserve spacing and newlines but don't wrap text. + + "pre" does not wrap well on Firefox, even with word-wrap:break-word. + "pre" on Chrome works with word-wrap, but exhibits different behavior: + Instead of entire words being moved to the next line for wrapping, + the browser will cut words in the middle for wrapping. + "pre-line" has Firefox issues + */ + white-space: pre-wrap; + /* Required for wrapping lines in Webkit, + but not necessary in Firefox if you have white-space wrapping + (pre-wrap, normal, pre-line) already set */ + word-wrap: break-word; + overflow-wrap: break-word; +} + +/* FlexiColorPicker */ + +.picker-wrapper, +.slide-wrapper { + position: relative; + float: left; +} + +.picker-indicator, +.slide-indicator { + position: absolute; + left: 0; + top: 0; + pointer-events: none; +} + +.picker, +.slide { + cursor: crosshair; + float: left; +} + +.slide-wrapper { + margin-left: 10px; +} + +.picker-indicator { + width: 5px; + height: 5px; + border: 2px solid darkblue; + -moz-border-radius: 4px; + -o-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + opacity: .5; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50); + filter: alpha(opacity=50); + background-color: white; +} + +.slide-indicator { + width: 100%; + height: 10px; + left: -4px; + opacity: .6; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=60); + filter: alpha(opacity=60); + border: 4px solid lightblue; + -moz-border-radius: 4px; + -o-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + background-color: white; +} + +/* http://www.mobify.com/blog/multiline-ellipsis-in-pure-css/ */ + +.EllipsisMultilineText { + overflow: hidden; + max-height: 2.6em; + line-height: 1.3em; +} + +.EllipsisMultilineText:before { + content:""; + float: left; + width: 5px; + max-height: 2.6em; +} + +.EllipsisMultilineText > *:first-child { + float: right; + width: 100%; + margin-top: 0px; + margin-bottom: 0px; + margin-left: -5px; + word-wrap: break-word; +} + +.EllipsisMultilineText:after { + content: "\02026"; + + box-sizing: content-box; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + + float: right; position: relative; + top: 1.3em; left: 100%; + width: 3em; margin-left: -3em; + padding-right: 5px; + + text-align: right; +} + +/* resize */ + +.ResizeLeft, .ResizeLeft:hover { + position: relative; + float: left; + height: 100%; + width: 10px; +} + +.ResizeLeft:hover{ + cursor: col-resize; +} + +/* virtual list */ + +.VirtualListRow { + position: absolute; + overflow: hidden; + white-space: nowrap; + display: inline-block; +} + +.VirtualListRow > .Text { + cursor: inherit; +} + +/* id */ + +#viewport { + position: absolute; + top: 32px; + left: 0px; + right: 300px; + bottom: 32px; +} + +#menubar { + position: absolute; + width: 100%; + height: 32px; + padding: 0px; + margin: 0px; + z-index: 100; + top: 0px; + left: 0px; +} + + #menubar .menu { + float: left; + cursor: pointer; + position: relative; + } + + #menubar .menu .title { + margin: 0px; + padding: 8px; + } + + #menubar .menu .options { + display: none; + padding: 5px 0px; + width: 140px; + position: absolute; + top: 32px; + } + + #menubar .menu:hover .options { + display: block; + max-height: 600px; + overflow: auto; + } + + #menubar .menu .options .option { + background-color: transparent; + padding: 5px 10px; + margin: 0px !important; + } + +#sidebar { + position: absolute; + right: 0px; + top: 32px; + bottom: 0px; + width: 300px; + overflow: hidden; +} + + #sidebar .Panel { + margin-bottom: 10px; + } + + #sidebar .Panel.collapsed { + margin-bottom: 0px; + } + + #sidebar .CollapsibleContent { + margin-top: 10px; + } + + #sidebar > .Panel { + padding: 10px; + border-top: 1px solid; + } + + #sidebar > .Content > .Panel { + padding: 10px; + border-top: 1px solid; + } + + #sidebar .Content { + top: 40px; + bottom: 0px; + position: absolute; + overflow: auto; + right: 0px; + width: 100%; + } + +#toolbar { + position: absolute; + left: 0px; + right: 300px; + bottom: 0px; + height: 32px; +} + + #toolbar .Panel { + padding: 6px; + } + + #toolbar button { + margin-right: 6px; + } diff --git a/examples/examples/embedded.html b/examples/examples/embedded.html new file mode 100644 index 000000000..3fcbfceb3 --- /dev/null +++ b/examples/examples/embedded.html @@ -0,0 +1,19 @@ + + + + NGL - embedded + + + + + + +
+ + diff --git a/examples/examples/fonts/FontAwesome.otf b/examples/examples/fonts/FontAwesome.otf new file mode 100644 index 0000000000000000000000000000000000000000..3461e3fce6a37f2321ecbe64707f04c0a4f05424 GIT binary patch literal 75188 zcmd42cYG5^*C@QQyeoNEmI+v3OJ1!hp?BN#Bql&0F(rUQ=*C61jEjsU_uhM#yN!)a zZ=nSOfy5~U0x2Yzbn+xmdPp$|WF(Ia_sq&BJV=l2St!J@u6Ld}hLIigG(oNmSNVYp2bu*`8&mCT(g%JrKs|W6VjPjD7@?@<57`EsF_Gij(~7S;$jX z2uy5njLz_R|~-giuu0_{g+f+ve88OQ{Hz6>Y}qGm4HH8LdoEP_Ir~wHA13xKq37E z1Q7#%ImkKEQfdVC%s|@tAvjG9rGf|G%tLS)wVE;wz~z*JdUGJ{Lb24ffiy>{sLuw{ zN=i%p4&x(nc7ggcB(4K#2{l|&I*@jvl#*QoX(=^T^1?vc`5_#d8Y8(m0B0V8%cxE# z$pBnVc{p_qq+KX?r%B0{5Tf&5n`|=c zVocso$A%h=aRy_sSr<0ddtr36w}@);HtI||V*&u5GQ^q}ChAOv7#*33dEO5J<`I%J z*XfL=NJFf*@6;JnrxS?Jv(dU>lMZNv>x|xJgST0)^ZvUTCS9nR;D;OFCALM<4|cS0 zYNX*m0;fd-nOKu<8nuWrP;pc;Wuzjh2ue?xfq7<9)2SJhFQgVyVemeL(m{GHV42{( zj*5ZUn|hjxr9$DY5z3R_VDViTHB~GZO+`ceH&s%?2xUzWj8p>r63nNdWGs|hNF|Ez z3_x2)t$`3h#RG+4z;(3FM9l*V{~4dWakP0RwGPS}p_WLIvN!Z%D)eP4^k@*r2UcJ- zU?=@*H?{x2(58Ba^p5QH?|rs+TW>_~_TISOtlp~Lj^1Ov-M!a( zzv}J1P2C=H+Z$+4xIO*0|LtdQZ@V3LJL`7U?T*{WZg=0lcKa(r`~KGyb$|2y)%O?P zpZ?_!U)FuOW{B$$#SnIg%Mkex*jk1-50MUW8X_4&x!rfW>vqTOPq#nZZoBom{jU7N z?Kihy-F|Vq<@U4NPi{ZD{owY!+jnl?x_#sJZ|;=H59|LA1MdHSc=vyM#lTJ^gTau`vLeC!n{ysFfXP_Uc`a;;df9b8Q`%5CI-q;j?f_Z z08@+f2t13LIfyd|dpIWbJ7SE2M+X6Y`2Iv zkp55o6=8%9;E*zdF@cM1gm+?lAU^<05&JWMOK=9?GfrY#nxQ=#37!98@E7s2C_kX( zC)VL8>pEDTzy|wG(u4WIx(CZZyip8U549cAFn<07M;srB30*Ni03+$ax};f-cVgcG z?mU=>^dM|7CT$V}dFOaPnef&?TC8tyti(D1AN0WcgLMzq`5)sfN=5Jn`%Q2L%ZV|e zl|>C1nDg+#cYyEwFueh|8;M1@qnrlv{tx2;EpI}L@Bj%;S(HBnvCo4r5Z3J3VAh|L z<;C|91Fq}f+8ik7{a@>YGGgBWt|0H6vm9+D_>zG%!GU*vgSez_v3`gN?0**q@gSZe z&4DsfsLMf%#B&~$%c2BmvjBC70pNldvK)OGz|)9*7$^_8{)72JI)izrZzX|2bz&g6 z5X63xu^GT)2Fno{M$)8hgZ%>hi3CQMO{9n`r5)Xz4^*h=``X=^^&>Ji>7z6GQLVJL| z_aKddx*yOSg#T~iaf59p@jw_#VuBCxViH3?=0bWXsoR0$7|#Km$Kk!l!}JNx|I;6t zQ24u_Le9kh{ZB$TOd^pe9yTF>YR?YaZFd!x{0fp_1!PlmxoWQIAlbaCRI;O$No?ms&tQPAvhI zcLfzlZKi@i0oH?3y#tirbSj%Fr|PH{s)IU29j9KRy5UrMnfj3Wg8G5#rT(J&;SlaD zkxPb1R1%Fukc^g0koZa-mn@S6N`fTOk~m4Kq)<{PX_a(J4ogl*PD{>7UX{Elxh%OM z`M2a}$#0TBB}j75iFF$8q;VSOd9(^983P8*!UoeWONP6bYtPEAf-PDhGoA5e9%B|W&ob+o%}g+} zor!0%nS7>*zlX3A#CmdZBB z^s;1GuB<{3O7?^7SJ@vjyIdjH$RCx@kk69Omp?9FB3~hY zP97?ck{jen@yA4hRgPR6M?4L6qa z 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�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 DgjuED literal 0 HcmV?d00001 diff --git a/examples/examples/fonts/fontawesome-webfont.eot b/examples/examples/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..6cfd56609567bc9db55186415c694d1d32808fc2 GIT binary patch literal 72449 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
U~M!&>g0b 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 literal 0 HcmV?d00001 diff --git a/examples/examples/fonts/fontawesome-webfont.svg b/examples/examples/fonts/fontawesome-webfont.svg new file mode 100644 index 000000000..a9f846950 --- /dev/null +++ b/examples/examples/fonts/fontawesome-webfont.svg @@ -0,0 +1,504 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/examples/fonts/fontawesome-webfont.ttf b/examples/examples/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..5cd6cff6d6f6cf438a882e366420dbcc5dddd3f1 GIT binary patch literal 141564 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ƓCICn66&u!PHl6pn& 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%0D%8GQ!Ai?6y^fVUY%4hi>cI9O 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
KT23~?3Dw&p)A=062yj$!;@;Sv13 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 + + + NGL - grid + + + + + + +

Grid

+ + diff --git a/examples/examples/js/gui.js b/examples/examples/js/gui.js new file mode 100644 index 000000000..fca61e7b7 --- /dev/null +++ b/examples/examples/js/gui.js @@ -0,0 +1,2394 @@ +/** + * @file Gui + * @author Alexander Rose + */ + +HTMLElement.prototype.getBoundingClientRect = (function () { + // workaround for ie11 behavior with disconnected dom nodes + + var _getBoundingClientRect = HTMLElement.prototype.getBoundingClientRect + + return function getBoundingClientRect () { + try { + return _getBoundingClientRect.apply(this, arguments) + } catch (e) { + return { + top: 0, + left: 0, + width: this.width, + height: this.height + } + } + } +}()) + +NGL.Widget = function () { + +} + +NGL.Widget.prototype = { + constructor: NGL.Widget +} + +NGL.createParameterInput = function (p, v) { + if (!p) return + + var value = v === undefined ? p.value : v + var input + + if (p.type === 'number') { + input = new UI.Number(0) + .setRange(p.min, p.max) + .setPrecision(p.precision) + .setValue(parseFloat(value)) + } else if (p.type === 'integer') { + input = new UI.Integer(parseInt(value)) + .setRange(p.min, p.max) + } else if (p.type === 'range') { + input = new UI.Range(p.min, p.max, value, p.step) + .setValue(parseFloat(value)) + } else if (p.type === 'boolean') { + input = new UI.Checkbox(value) + } else if (p.type === 'text') { + input = new UI.Input(value) + } else if (p.type === 'select') { + input = new UI.Select() + .setWidth('') + .setOptions(p.options) + .setValue(value) + } else if (p.type === 'color') { + input = new UI.ColorPopupMenu(p.label) + .setValue(value) + } else if (p.type === 'vector3') { + input = new UI.Vector3(value) + .setPrecision(p.precision) + } else if (p.type === 'hidden') { + + // nothing to display + + } else { + console.warn( + 'NGL.createParameterInput: unknown parameter type ' + + "'" + p.type + "'" + ) + } + + return input +} + +/// ///////////// +// Preferences + +NGL.Preferences = function (id, defaultParams) { + this.signals = { + keyChanged: new signals.Signal() + } + + this.id = id || 'ngl-gui' + var dp = Object.assign({}, defaultParams) + + this.storage = { + impostor: true, + quality: 'auto', + sampleLevel: 0, + theme: 'dark', + backgroundColor: 'black', + overview: true, + rotateSpeed: 2.0, + zoomSpeed: 1.2, + panSpeed: 0.8, + clipNear: 0, + clipFar: 100, + clipDist: 10, + fogNear: 50, + fogFar: 100, + cameraFov: 40, + cameraType: 'perspective', + lightColor: 0xdddddd, + lightIntensity: 1.0, + ambientColor: 0xdddddd, + ambientIntensity: 0.2, + hoverTimeout: 0 + } + + // overwrite default values with params + for (var key in this.storage) { + if (dp[ key ] !== undefined) { + this.storage[ key ] = dp[ key ] + } + } + + try { + if (window.localStorage[ this.id ] === undefined) { + window.localStorage[ this.id ] = JSON.stringify(this.storage) + } else { + var data = JSON.parse(window.localStorage[ this.id ]) + for (var key in data) { + this.storage[ key ] = data[ key ] + } + } + } catch (e) { + NGL.error('localStorage not accessible/available') + } +} + +NGL.Preferences.prototype = { + + constructor: NGL.Preferences, + + getKey: function (key) { + return this.storage[ key ] + }, + + setKey: function (key, value) { + this.storage[ key ] = value + + try { + window.localStorage[ this.id ] = JSON.stringify(this.storage) + this.signals.keyChanged.dispatch(key, value) + } catch (e) { + // Webkit === 22 / Firefox === 1014 + if (e.code === 22 || e.code === 1014) { + NGL.error('localStorage full') + } else { + NGL.error('localStorage not accessible/available', e) + } + } + }, + + clear: function () { + try { + delete window.localStorage[ this.id ] + } catch (e) { + NGL.error('localStorage not accessible/available') + } + } + +} + +// Stage + +NGL.StageWidget = function (stage) { + var viewport = new NGL.ViewportWidget(stage).setId('viewport') + document.body.appendChild(viewport.dom) + + // ensure initial focus on viewer canvas for key-stroke listening + stage.viewer.renderer.domElement.focus() + + // + + var preferences = new NGL.Preferences('ngl-stage-widget') + + var pp = {} + for (var name in preferences.storage) { + pp[ name ] = preferences.getKey(name) + } + stage.setParameters(pp) + + preferences.signals.keyChanged.add(function (key, value) { + var sp = {} + sp[ key ] = value + stage.setParameters(sp) + if (key === 'theme') { + setTheme(value) + } + }, this) + + // + + var cssLinkElement = document.createElement('link') + cssLinkElement.rel = 'stylesheet' + cssLinkElement.id = 'theme' + + function setTheme (value) { + var cssPath, bgColor + if (value === 'light') { + cssPath = NGL.cssDirectory + 'light.css' + bgColor = 'white' + } else { + cssPath = NGL.cssDirectory + 'dark.css' + bgColor = 'black' + } + cssLinkElement.href = cssPath + stage.setParameters({ backgroundColor: bgColor }) + } + + setTheme(preferences.getKey('theme')) + document.head.appendChild(cssLinkElement) + + // + + var toolbar = new NGL.ToolbarWidget(stage).setId('toolbar') + document.body.appendChild(toolbar.dom) + + var menubar = new NGL.MenubarWidget(stage, preferences).setId('menubar') + document.body.appendChild(menubar.dom) + + var sidebar = new NGL.SidebarWidget(stage).setId('sidebar') + document.body.appendChild(sidebar.dom) + + // + + document.body.style.touchAction = 'none' + + // + + stage.handleResize() + // FIXME hack for ie11 + setTimeout(function () { stage.handleResize() }, 500) + + // + + var doResizeLeft = false + var movedResizeLeft = false + var minResizeLeft = false + + var handleResizeLeft = function (clientX) { + if (clientX >= 50 && clientX <= window.innerWidth - 10) { + sidebar.setWidth(window.innerWidth - clientX + 'px') + viewport.setWidth(clientX + 'px') + toolbar.setWidth(clientX + 'px') + stage.handleResize() + } + var sidebarWidth = sidebar.dom.getBoundingClientRect().width + if (clientX === undefined) { + var mainWidth = window.innerWidth - sidebarWidth + viewport.setWidth(mainWidth + 'px') + toolbar.setWidth(mainWidth + 'px') + stage.handleResize() + } + if (sidebarWidth <= 10) { + minResizeLeft = true + } else { + minResizeLeft = false + } + } + handleResizeLeft = NGL.throttle( + handleResizeLeft, 50, { leading: true, trailing: true } + ) + + var resizeLeft = new UI.Panel() + .setClass('ResizeLeft') + .onMouseDown(function () { + doResizeLeft = true + movedResizeLeft = false + }) + .onClick(function () { + if (minResizeLeft) { + handleResizeLeft(window.innerWidth - 300) + } else if (!doResizeLeft && !movedResizeLeft) { + handleResizeLeft(window.innerWidth - 10) + } + }) + + sidebar.add(resizeLeft) + + window.addEventListener( + 'mousemove', function (event) { + if (doResizeLeft) { + document.body.style.cursor = 'col-resize' + movedResizeLeft = true + handleResizeLeft(event.clientX) + } + }, false + ) + + window.addEventListener( + 'mouseup', function (event) { + doResizeLeft = false + document.body.style.cursor = '' + }, false + ) + + window.addEventListener( + 'resize', function (event) { + handleResizeLeft() + }, false + ) + + // + + document.addEventListener('dragover', function (e) { + e.stopPropagation() + e.preventDefault() + e.dataTransfer.dropEffect = 'none' + }, false) + + document.addEventListener('drop', function (e) { + e.stopPropagation() + e.preventDefault() + }, false) + + this.viewport = viewport + this.toolbar = toolbar + this.menubar = menubar + this.sidebar = sidebar + + return this +} + +// Viewport + +NGL.ViewportWidget = function (stage) { + var viewer = stage.viewer + var renderer = viewer.renderer + + var container = new UI.Panel() + container.dom = viewer.container + container.setPosition('absolute') + + var fileTypesOpen = NGL.flatten([ + NGL.ParserRegistry.getStructureExtensions(), + NGL.ParserRegistry.getVolumeExtensions(), + NGL.ParserRegistry.getSurfaceExtensions(), + NGL.DecompressorRegistry.names + ]) + + // event handlers + + container.dom.addEventListener('dragover', function (e) { + e.stopPropagation() + e.preventDefault() + e.dataTransfer.dropEffect = 'copy' + }, false) + + container.dom.addEventListener('drop', function (e) { + e.stopPropagation() + e.preventDefault() + + var fn = function (file, callback) { + var ext = file.name.split('.').pop().toLowerCase() + if (NGL.ScriptExtensions.includes(ext)) { + stage.loadScript(file).then(callback) + } else if (fileTypesOpen.includes(ext)) { + stage.loadFile(file, { defaultRepresentation: true }).then(callback) + } else { + console.error('unknown filetype: ' + ext) + callback() + } + } + var queue = new NGL.Queue(fn, e.dataTransfer.files) + }, false) + + return container +} + +// Toolbar + +NGL.ToolbarWidget = function (stage) { + var container = new UI.Panel() + + var messageText = new UI.Text() + var messagePanel = new UI.Panel() + .setDisplay('inline') + .setFloat('left') + .add(messageText) + + var statsText = new UI.Text() + var statsPanel = new UI.Panel() + .setDisplay('inline') + .setFloat('right') + .add(statsText) + + stage.signals.clicked.add(function (pickingProxy) { + messageText.setValue(pickingProxy ? pickingProxy.getLabel() : 'nothing') + }) + + stage.viewer.stats.signals.updated.add(function () { + if (NGL.Debug) { + statsText.setValue( + stage.viewer.stats.lastDuration.toFixed(2) + ' ms | ' + + stage.viewer.stats.lastFps + ' fps' + ) + } else { + statsText.setValue('') + } + }) + + container.add(messagePanel, statsPanel) + + return container +} + +// Menubar + +NGL.MenubarWidget = function (stage, preferences) { + var container = new UI.Panel() + + container.add(new NGL.MenubarFileWidget(stage)) + container.add(new NGL.MenubarViewWidget(stage, preferences)) + if (NGL.examplesListUrl && NGL.examplesScriptUrl) { + container.add(new NGL.MenubarExamplesWidget(stage)) + } + container.add(new NGL.MenubarHelpWidget(stage, preferences)) + + container.add( + new UI.Panel().setClass('menu').setFloat('right').add( + new UI.Text('NGL Viewer ' + NGL.Version).setClass('title') + ) + ) + + return container +} + +NGL.MenubarFileWidget = function (stage) { + var fileTypesOpen = NGL.flatten([ + NGL.ParserRegistry.getStructureExtensions(), + NGL.ParserRegistry.getVolumeExtensions(), + NGL.ParserRegistry.getSurfaceExtensions(), + NGL.DecompressorRegistry.names, + NGL.ScriptExtensions + ]) + + function fileInputOnChange (e) { + var fn = function (file, callback) { + var ext = file.name.split('.').pop().toLowerCase() + if (NGL.ScriptExtensions.includes(ext)) { + stage.loadScript(file).then(callback) + } else if (fileTypesOpen.includes(ext)) { + stage.loadFile(file, { defaultRepresentation: true }).then(callback) + } else { + console.error('unknown filetype: ' + ext) + callback() + } + } + var queue = new NGL.Queue(fn, e.target.files) + } + + var fileInput = document.createElement('input') + fileInput.type = 'file' + fileInput.multiple = true + fileInput.style.display = 'none' + fileInput.accept = '.' + fileTypesOpen.join(',.') + fileInput.addEventListener('change', fileInputOnChange, false) + + // export image + + var exportImageWidget = new NGL.ExportImageWidget(stage) + .setDisplay('none') + .attach() + + // event handlers + + function onOpenOptionClick () { + fileInput.click() + } + + function onImportOptionClick () { + var dirWidget + function onListingClick (info) { + var ext = info.path.split('.').pop().toLowerCase() + if (NGL.ScriptExtensions.includes(ext)) { + stage.loadScript(NGL.ListingDatasource.getUrl(info.path)) + dirWidget.dispose() + } else if (fileTypesOpen.includes(ext)) { + stage.loadFile(NGL.ListingDatasource.getUrl(info.path), { + defaultRepresentation: true + }) + dirWidget.dispose() + } else { + console.error('unknown filetype: ' + ext) + } + } + + dirWidget = new NGL.DirectoryListingWidget( + NGL.ListingDatasource, stage, 'Import file', + fileTypesOpen, onListingClick + ) + + dirWidget + .setOpacity('0.9') + .setLeft('50px') + .setTop('80px') + .attach() + } + + function onExportImageOptionClick () { + exportImageWidget + .setOpacity('0.9') + .setLeft('50px') + .setTop('80px') + .setDisplay('block') + } + + function onScreenshotOptionClick () { + stage.makeImage({ + factor: 1, + antialias: true, + trim: false, + transparent: false + }).then(function (blob) { + NGL.download(blob, 'screenshot.png') + }) + } + + function onPdbInputKeyDown (e) { + if (e.keyCode === 13) { + stage.loadFile('rcsb://' + e.target.value.trim(), { + defaultRepresentation: true + }) + e.target.value = '' + } + } + + function onAsTrajectoryChange (e) { + stage.defaultFileParams.asTrajectory = e.target.checked + } + + function onFirstModelOnlyChange (e) { + stage.defaultFileParams.firstModelOnly = e.target.checked + } + + function onCAlphaOnlyChange (e) { + stage.defaultFileParams.cAlphaOnly = e.target.checked + } + + // configure menu contents + + var createOption = UI.MenubarHelper.createOption + var createInput = UI.MenubarHelper.createInput + var createCheckbox = UI.MenubarHelper.createCheckbox + var createDivider = UI.MenubarHelper.createDivider + + var menuConfig = [ + createOption('Open...', onOpenOptionClick), + createInput('PDB', onPdbInputKeyDown), + createCheckbox('asTrajectory', false, onAsTrajectoryChange), + createCheckbox('firstModelOnly', false, onFirstModelOnlyChange), + createCheckbox('cAlphaOnly', false, onCAlphaOnlyChange), + createDivider(), + createOption('Screenshot', onScreenshotOptionClick, 'camera'), + createOption('Export image...', onExportImageOptionClick) + ] + + if (NGL.ListingDatasource) { + menuConfig.splice( + 1, 0, createOption('Import...', onImportOptionClick) + ) + } + + var optionsPanel = UI.MenubarHelper.createOptionsPanel(menuConfig) + optionsPanel.dom.appendChild(fileInput) + + return UI.MenubarHelper.createMenuContainer('File', optionsPanel) +} + +NGL.MenubarViewWidget = function (stage, preferences) { + // event handlers + + function onLightThemeOptionClick () { + preferences.setKey('theme', 'light') + } + + function onDarkThemeOptionClick () { + preferences.setKey('theme', 'dark') + } + + function onPerspectiveCameraOptionClick () { + stage.setParameters({ cameraType: 'perspective' }) + } + + function onOrthographicCameraOptionClick () { + stage.setParameters({ cameraType: 'orthographic' }) + } + + function onStereoCameraOptionClick () { + stage.setParameters({ cameraType: 'stereo' }) + } + + function onFullScreenOptionClick () { + stage.toggleFullscreen(document.body) + } + + function onCenterOptionClick () { + stage.autoView(1000) + } + + function onToggleSpinClick () { + stage.toggleSpin() + } + + function onToggleRockClick () { + stage.toggleRock() + } + + function onGetOrientationClick () { + window.prompt( + 'Get orientation', + JSON.stringify( + stage.viewerControls.getOrientation().toArray(), + function (k, v) { + return v.toFixed ? Number(v.toFixed(2)) : v + } + ) + ) + } + + function onSetOrientationClick () { + stage.viewerControls.orient( + JSON.parse(window.prompt('Set orientation')) + ) + } + + stage.signals.fullscreenChanged.add(function (isFullscreen) { + var icon = menuConfig[ 6 ].children[ 0 ] + if (isFullscreen) { + icon.switchClass('compress', 'expand') + } else { + icon.switchClass('expand', 'compress') + } + }) + + // configure menu contents + + var createOption = UI.MenubarHelper.createOption + var createDivider = UI.MenubarHelper.createDivider + + var menuConfig = [ + createOption('Light theme', onLightThemeOptionClick), + createOption('Dark theme', onDarkThemeOptionClick), + createDivider(), + createOption('Perspective', onPerspectiveCameraOptionClick), + createOption('Orthographic', onOrthographicCameraOptionClick), + createOption('Stereo', onStereoCameraOptionClick), + createDivider(), + createOption('Full screen', onFullScreenOptionClick, 'expand'), + createOption('Center', onCenterOptionClick, 'bullseye'), + createDivider(), + createOption('Toggle spin', onToggleSpinClick), + createOption('Toggle rock', onToggleRockClick), + createDivider(), + createOption('Get orientation', onGetOrientationClick), + createOption('Set orientation', onSetOrientationClick) + ] + + var optionsPanel = UI.MenubarHelper.createOptionsPanel(menuConfig) + + return UI.MenubarHelper.createMenuContainer('View', optionsPanel) +} + +NGL.MenubarExamplesWidget = function (stage) { + // configure menu contents + + var createOption = UI.MenubarHelper.createOption + var optionsPanel = UI.MenubarHelper.createOptionsPanel([]) + optionsPanel.setWidth('300px') + + var xhr = new XMLHttpRequest() + xhr.open('GET', NGL.examplesListUrl) + xhr.responseType = 'json' + xhr.onload = function (e) { + var response = this.response + if (typeof response === 'string') { + // for ie11 + response = JSON.parse(response) + } + response.sort().forEach(function (name) { + var option = createOption(name, function () { + stage.loadScript(NGL.examplesScriptUrl + name + '.js') + }) + optionsPanel.add(option) + }) + } + xhr.send() + + return UI.MenubarHelper.createMenuContainer('Examples', optionsPanel) +} + +NGL.MenubarHelpWidget = function (stage, preferences) { + // event handlers + + function onOverviewOptionClick () { + overviewWidget + .setOpacity('0.9') + .setDisplay('block') + .setWidgetPosition(50, 80) + } + + function onDocOptionClick () { + window.open(NGL.documentationUrl, '_blank') + } + + function onDebugOnClick () { + NGL.setDebug(true) + stage.viewer.updateHelper() + stage.viewer.requestRender() + } + + function onDebugOffClick () { + NGL.setDebug(false) + stage.viewer.updateHelper() + stage.viewer.requestRender() + } + + function onPreferencesOptionClick () { + preferencesWidget + .setOpacity('0.9') + .setDisplay('block') + .setWidgetPosition(50, 80) + } + + // export image + + var preferencesWidget = new NGL.PreferencesWidget(stage, preferences) + .setDisplay('none') + .attach() + + // overview + + var overviewWidget = new NGL.OverviewWidget(stage, preferences) + .setDisplay('none') + .attach() + + if (preferences.getKey('overview')) { + onOverviewOptionClick() + } + + // configure menu contents + + var createOption = UI.MenubarHelper.createOption + var createDivider = UI.MenubarHelper.createDivider + + var menuConfig = [ + createOption('Overview', onOverviewOptionClick), + createOption('Documentation', onDocOptionClick), + createDivider(), + createOption('Debug on', onDebugOnClick), + createOption('Debug off', onDebugOffClick), + createDivider(), + createOption('Preferences', onPreferencesOptionClick, 'sliders') + ] + + var optionsPanel = UI.MenubarHelper.createOptionsPanel(menuConfig) + + return UI.MenubarHelper.createMenuContainer('Help', optionsPanel) +} + +// Overview + +NGL.OverviewWidget = function (stage, preferences) { + var container = new UI.OverlayPanel() + + var xOffset = 0 + var yOffset = 0 + + var prevX = 0 + var prevY = 0 + + function onMousemove (e) { + if (prevX === 0) { + prevX = e.clientX + prevY = e.clientY + } + xOffset -= prevX - e.clientX + yOffset -= prevY - e.clientY + prevX = e.clientX + prevY = e.clientY + container.dom.style.top = yOffset + 'px' + container.dom.style.left = xOffset + 'px' + } + + function setWidgetPosition (left, top) { + xOffset = left + yOffset = top + prevX = 0 + prevY = 0 + container.dom.style.top = yOffset + 'px' + container.dom.style.left = xOffset + 'px' + } + container.setWidgetPosition = setWidgetPosition + + var headingPanel = new UI.Panel() + .setBorderBottom('1px solid #555') + .setHeight('25px') + .setCursor('move') + .onMouseDown(function (e) { + if (e.which === 1) { + document.addEventListener('mousemove', onMousemove) + } + document.addEventListener('mouseup', function (e) { + document.removeEventListener('mousemove', onMousemove) + }) + }) + + var listingPanel = new UI.Panel() + .setMarginTop('10px') + .setMinHeight('100px') + .setMaxHeight('500px') + .setMaxWidth('600px') + .setOverflow('auto') + + headingPanel.add( + new UI.Text('NGL Viewer').setFontStyle('italic'), + new UI.Html(' — Overview') + ) + headingPanel.add( + new UI.Icon('times') + .setCursor('pointer') + .setMarginLeft('20px') + .setFloat('right') + .onClick(function () { + container.setDisplay('none') + }) + ) + + container.add(headingPanel) + container.add(listingPanel) + + // + + function addIcon (name, text) { + var panel = new UI.Panel() + + var icon = new UI.Icon(name) + .setWidth('20px') + .setFloat('left') + + var label = new UI.Text(text) + .setDisplay('inline') + .setMarginLeft('5px') + + panel + .setMarginLeft('20px') + .add(icon, label) + listingPanel.add(panel) + } + + listingPanel + .add(new UI.Panel().add(new UI.Html("To load a new structure use the File menu in the top left via drag'n'drop."))) + .add(new UI.Break()) + + listingPanel + .add(new UI.Panel().add(new UI.Text('A number of clickable icons provide common actions. Most icons can be clicked on, just try it or hover the mouse pointer over it to see a tooltip.'))) + .add(new UI.Break()) + + addIcon('eye', 'Controls the visibility of a component.') + addIcon('trash-o', 'Deletes a component. Note that a second click is required to confirm the action.') + addIcon('bullseye', 'Centers a component.') + addIcon('bars', 'Opens a menu with further options.') + addIcon('square', 'Opens a menu with coloring options.') + addIcon('filter', 'Indicates atom-selection input fields.') + + listingPanel + .add(new UI.Text('Mouse controls')) + .add(new UI.Html( + '
    ' + + '
  • Left button hold and move to rotate camera around center.
  • ' + + '
  • Left button click to pick atom.
  • ' + + '
  • Middle button hold and move to zoom camera in and out.
  • ' + + '
  • Middle button click to center camera on atom.
  • ' + + '
  • Right button hold and move to translate camera in the screen plane.
  • ' + + '
' + )) + + listingPanel + .add(new UI.Panel().add(new UI.Html( + 'For more information please visit the ' + + "
documentation pages." + ))) + + var overview = preferences.getKey('overview') + var showOverviewCheckbox = new UI.Checkbox(overview) + .onClick(function () { + preferences.setKey( + 'overview', + showOverviewCheckbox.getValue() + ) + }) + + listingPanel + .add(new UI.HorizontalRule() + .setBorderTop('1px solid #555') + .setMarginTop('15px') + ) + .add(new UI.Panel().add( + showOverviewCheckbox, + new UI.Text( + 'Show on startup. Always available from Menu > Help > Overview.' + ).setMarginLeft('5px') + )) + + return container +} + +// Preferences + +NGL.PreferencesWidget = function (stage, preferences) { + var container = new UI.OverlayPanel() + + var xOffset = 0 + var yOffset = 0 + + var prevX = 0 + var prevY = 0 + + function onMousemove (e) { + if (prevX === 0) { + prevX = e.clientX + prevY = e.clientY + } + xOffset -= prevX - e.clientX + yOffset -= prevY - e.clientY + prevX = e.clientX + prevY = e.clientY + container.dom.style.top = yOffset + 'px' + container.dom.style.left = xOffset + 'px' + } + + function setWidgetPosition (left, top) { + xOffset = left + yOffset = top + prevX = 0 + prevY = 0 + container.dom.style.top = yOffset + 'px' + container.dom.style.left = xOffset + 'px' + } + container.setWidgetPosition = setWidgetPosition + + var headingPanel = new UI.Panel() + .setBorderBottom('1px solid #555') + .setHeight('25px') + .setCursor('move') + .onMouseDown(function (e) { + if (e.which === 1) { + document.addEventListener('mousemove', onMousemove) + } + document.addEventListener('mouseup', function (e) { + document.removeEventListener('mousemove', onMousemove) + }) + }) + + var listingPanel = new UI.Panel() + .setMarginTop('10px') + .setMinHeight('100px') + .setMaxHeight('500px') + .setOverflow('auto') + + headingPanel.add(new UI.Text('Preferences')) + headingPanel.add( + new UI.Icon('times') + .setCursor('pointer') + .setMarginLeft('20px') + .setFloat('right') + .onClick(function () { + container.setDisplay('none') + }) + ) + + container.add(headingPanel) + container.add(listingPanel) + + // + + Object.keys(NGL.UIStageParameters).forEach(function (name) { + var p = NGL.UIStageParameters[ name ] + if (p.label === undefined) p.label = name + var input = NGL.createParameterInput(p, stage.parameters[ name ]) + + if (!input) return + + preferences.signals.keyChanged.add(function (key, value) { + if (key === name) input.setValue(value) + }) + + function setParam () { + var sp = {} + sp[ name ] = input.getValue() + preferences.setKey(name, sp[ name ]) + } + + var ua = navigator.userAgent + if (p.type === 'range' && !/Trident/.test(ua) && !/MSIE/.test(ua)) { + input.onInput(setParam) + } else { + input.onChange(setParam) + } + + listingPanel + .add(new UI.Text(name).setWidth('120px')) + .add(input) + .add(new UI.Break()) + }) + + return container +} + +// Export image + +NGL.ExportImageWidget = function (stage) { + var container = new UI.OverlayPanel() + + var headingPanel = new UI.Panel() + .setBorderBottom('1px solid #555') + .setHeight('25px') + + var listingPanel = new UI.Panel() + .setMarginTop('10px') + .setMinHeight('100px') + .setMaxHeight('500px') + .setOverflow('auto') + + headingPanel.add(new UI.Text('Image export')) + headingPanel.add( + new UI.Icon('times') + .setCursor('pointer') + .setMarginLeft('20px') + .setFloat('right') + .onClick(function () { + container.setDisplay('none') + }) + ) + + container.add(headingPanel) + container.add(listingPanel) + + var factorSelect = new UI.Select() + .setOptions({ + '1': '1x', + '2': '2x', + '3': '3x', + '4': '4x', + '5': '5x', + '6': '6x', + '7': '7x', + '8': '8x', + '9': '9x', + '10': '10x' + }) + .setValue('4') + + var antialiasCheckbox = new UI.Checkbox() + .setValue(true) + + var trimCheckbox = new UI.Checkbox() + .setValue(false) + + var transparentCheckbox = new UI.Checkbox() + .setValue(false) + + var progress = new UI.Progress() + .setDisplay('none') + + var exportButton = new UI.Button('export') + .onClick(function () { + exportButton.setDisplay('none') + progress.setDisplay('inline-block') + function onProgress (i, n, finished) { + if (i === 1) { + progress.setMax(n) + } + if (i >= n) { + progress.setIndeterminate() + } else { + progress.setValue(i) + } + if (finished) { + progress.setDisplay('none') + exportButton.setDisplay('inline-block') + } + } + + setTimeout(function () { + stage.makeImage({ + factor: parseInt(factorSelect.getValue()), + antialias: antialiasCheckbox.getValue(), + trim: trimCheckbox.getValue(), + transparent: transparentCheckbox.getValue(), + onProgress: onProgress + }).then(function (blob) { + NGL.download(blob, 'screenshot.png') + }) + }, 50) + }) + + function addEntry (label, entry) { + listingPanel + .add(new UI.Text(label).setWidth('80px')) + .add(entry || new UI.Panel()) + .add(new UI.Break()) + } + + addEntry('scale', factorSelect) + addEntry('antialias', antialiasCheckbox) + addEntry('trim', trimCheckbox) + addEntry('transparent', transparentCheckbox) + + listingPanel.add( + new UI.Break(), + exportButton, progress + ) + + return container +} + +// Sidebar + +NGL.SidebarWidget = function (stage) { + var signals = stage.signals + var container = new UI.Panel() + + var widgetContainer = new UI.Panel() + .setClass('Content') + + var compList = [] + var widgetList = [] + + signals.componentAdded.add(function (component) { + var widget + + switch (component.type) { + case 'structure': + widget = new NGL.StructureComponentWidget(component, stage) + break + + case 'surface': + widget = new NGL.SurfaceComponentWidget(component, stage) + break + + case 'volume': + widget = new NGL.VolumeComponentWidget(component, stage) + break + + case 'shape': + widget = new NGL.ShapeComponentWidget(component, stage) + break + + default: + console.warn('NGL.SidebarWidget: component type unknown', component) + return + } + + widgetContainer.add(widget) + + compList.push(component) + widgetList.push(widget) + }) + + signals.componentRemoved.add(function (component) { + var idx = compList.indexOf(component) + + if (idx !== -1) { + widgetList[ idx ].dispose() + + compList.splice(idx, 1) + widgetList.splice(idx, 1) + } + }) + + // actions + + var expandAll = new UI.Icon('plus-square') + .setTitle('expand all') + .setCursor('pointer') + .onClick(function () { + widgetList.forEach(function (widget) { + widget.expand() + }) + }) + + var collapseAll = new UI.Icon('minus-square') + .setTitle('collapse all') + .setCursor('pointer') + .setMarginLeft('10px') + .onClick(function () { + widgetList.forEach(function (widget) { + widget.collapse() + }) + }) + + var centerAll = new UI.Icon('bullseye') + .setTitle('center all') + .setCursor('pointer') + .setMarginLeft('10px') + .onClick(function () { + stage.autoView(1000) + }) + + var disposeAll = new UI.DisposeIcon() + .setMarginLeft('10px') + .setDisposeFunction(function () { + stage.removeAllComponents() + }) + + var settingsMenu = new UI.PopupMenu('cogs', 'Settings', 'window') + .setIconTitle('settings') + .setMarginLeft('10px') + settingsMenu.entryLabelWidth = '120px' + + // Busy indicator + + var busy = new UI.Panel() + .setDisplay('inline') + .add( + new UI.Icon('spinner') + .addClass('spin') + .setMarginLeft('45px') + ) + + stage.tasks.signals.countChanged.add(function (delta, count) { + if (count > 0) { + actions.add(busy) + } else { + try { + actions.remove(busy) + } catch (e) { + // already removed + } + } + }) + + var paramNames = [ + 'clipNear', 'clipFar', 'clipDist', 'fogNear', 'fogFar', + 'lightColor', 'lightIntensity', 'ambientColor', 'ambientIntensity' + ] + + paramNames.forEach(function (name) { + var p = NGL.UIStageParameters[ name ] + if (p.label === undefined) p.label = name + var input = NGL.createParameterInput(p, stage.parameters[ name ]) + + if (!input) return + + stage.signals.parametersChanged.add(function (params) { + input.setValue(params[ name ]) + }) + + function setParam () { + var sp = {} + sp[ name ] = input.getValue() + stage.setParameters(sp) + } + + var ua = navigator.userAgent + if (p.type === 'range' && !/Trident/.test(ua) && !/MSIE/.test(ua)) { + input.onInput(setParam) + } else { + input.onChange(setParam) + } + + settingsMenu.addEntry(name, input) + }) + + // + + var actions = new UI.Panel() + .setClass('Panel Sticky') + .add( + expandAll, + collapseAll, + centerAll, + disposeAll, + settingsMenu + ) + + container.add( + actions, + widgetContainer + ) + + return container +} + +// Component + +NGL.StructureComponentWidget = function (component, stage) { + var signals = component.signals + var container = new UI.CollapsibleIconPanel('minus-square', 'plus-square') + + var reprContainer = new UI.Panel() + var trajContainer = new UI.Panel() + + signals.representationAdded.add(function (repr) { + reprContainer.add( + new NGL.RepresentationElementWidget(repr, stage) + ) + }) + + signals.trajectoryAdded.add(function (traj) { + trajContainer.add(new NGL.TrajectoryElementWidget(traj, stage)) + }) + + signals.defaultAssemblyChanged.add(function () { + assembly.setValue(component.parameters.defaultAssembly) + }) + + // Selection + + container.add( + new UI.SelectionPanel(component.selection) + .setMarginLeft('20px') + .setInputWidth('214px') + ) + + // Export PDB + + var pdb = new UI.Button('export').onClick(function () { + var pdbWriter = new NGL.PdbWriter(component.structure) + pdbWriter.download('structure') + componentPanel.setMenuDisplay('none') + }) + + // Add representation + + var repr = new UI.Select() + .setColor('#444') + .setOptions((function () { + var reprOptions = { '': '[ add ]' } + NGL.RepresentationRegistry.names.forEach(function (key) { + reprOptions[ key ] = key + }) + return reprOptions + })()) + .onChange(function () { + component.addRepresentation(repr.getValue()) + repr.setValue('') + componentPanel.setMenuDisplay('none') + }) + + // Assembly + + var assembly = new UI.Select() + .setColor('#444') + .setOptions((function () { + var biomolDict = component.structure.biomolDict + var assemblyOptions = { + '': (component.structure.unitcell ? 'AU' : 'FULL') + } + Object.keys(biomolDict).forEach(function (k) { + assemblyOptions[ k ] = k + }) + return assemblyOptions + })()) + .setValue(component.parameters.defaultAssembly) + .onChange(function () { + component.setDefaultAssembly(assembly.getValue()) + componentPanel.setMenuDisplay('none') + }) + + // Open trajectory + + var trajExt = [] + NGL.ParserRegistry.getTrajectoryExtensions().forEach(function (ext) { + trajExt.push('.' + ext, '.' + ext + '.gz') + }) + + function framesInputOnChange (e) { + var fn = function (file, callback) { + NGL.autoLoad(file).then(function (frames) { + component.addTrajectory(frames) + callback() + }) + } + var queue = new NGL.Queue(fn, e.target.files) + e.target.value = '' + } + + var framesInput = document.createElement('input') + framesInput.type = 'file' + framesInput.multiple = true + framesInput.style.display = 'none' + framesInput.accept = trajExt.join(',') + framesInput.addEventListener('change', framesInputOnChange, false) + + var traj = new UI.Button('open').onClick(function () { + framesInput.click() + componentPanel.setMenuDisplay('none') + }) + + // Import remote trajectory + + var remoteTraj = new UI.Button('import').onClick(function () { + componentPanel.setMenuDisplay('none') + + // TODO list of extensions should be provided by trajectory datasource + var remoteTrajExt = [ + 'xtc', 'trr', 'netcdf', 'dcd', 'ncdf', 'nc', 'gro', 'pdb', + 'lammpstrj', 'xyz', 'mdcrd', 'gz', 'binpos', 'h5', 'dtr', + 'arc', 'tng', 'trj', 'trz' + ] + var dirWidget + + function onListingClick (info) { + var ext = info.path.split('.').pop().toLowerCase() + if (remoteTrajExt.indexOf(ext) !== -1) { + component.addTrajectory(info.path + '?struc=' + component.structure.path) + dirWidget.dispose() + } else { + NGL.log('unknown trajectory type: ' + ext) + } + } + + dirWidget = new NGL.DirectoryListingWidget( + NGL.ListingDatasource, stage, 'Import trajectory', + remoteTrajExt, onListingClick + ) + + dirWidget + .setOpacity('0.9') + .setLeft('50px') + .setTop('80px') + .attach() + }) + + // Superpose + + function setSuperposeOptions () { + var superposeOptions = { '': '[ structure ]' } + stage.eachComponent(function (o, i) { + if (o !== component) { + superposeOptions[ i ] = o.name + } + }, NGL.StructureComponent) + superpose.setOptions(superposeOptions) + } + + stage.signals.componentAdded.add(setSuperposeOptions) + stage.signals.componentRemoved.add(setSuperposeOptions) + + var superpose = new UI.Select() + .setColor('#444') + .onChange(function () { + component.superpose( + stage.compList[ superpose.getValue() ], + true + ) + component.autoView(1000) + superpose.setValue('') + componentPanel.setMenuDisplay('none') + }) + + setSuperposeOptions() + + // Principal axes + + var alignAxes = new UI.Button('align').onClick(function () { + var pa = component.structure.getPrincipalAxes() + var q = pa.getRotationQuaternion() + q.multiply(component.quaternion.clone().inverse()) + stage.animationControls.rotate(q) + stage.animationControls.move(component.getCenter()) + }) + + // Measurements removal + + var removeMeasurements = new UI.Button('remove').onClick(function () { + component.removeAllMeasurements() + }) + + // Annotations visibility + + var showAnnotations = new UI.Button('show').onClick(function () { + component.annotationList.forEach(function (annotation) { + annotation.setVisibility(true) + }) + }) + + var hideAnnotations = new UI.Button('hide').onClick(function () { + component.annotationList.forEach(function (annotation) { + annotation.setVisibility(false) + }) + }) + + var annotationButtons = new UI.Panel() + .setDisplay('inline-block') + .add(showAnnotations, hideAnnotations) + + // Open validation + + function validationInputOnChange (e) { + var fn = function (file, callback) { + NGL.autoLoad(file, { ext: 'validation' }).then(function (validation) { + component.structure.validation = validation + callback() + }) + } + var queue = new NGL.Queue(fn, e.target.files) + } + + var validationInput = document.createElement('input') + validationInput.type = 'file' + validationInput.style.display = 'none' + validationInput.accept = '.xml' + validationInput.addEventListener('change', validationInputOnChange, false) + + var vali = new UI.Button('open').onClick(function () { + validationInput.click() + componentPanel.setMenuDisplay('none') + }) + + // Position + + var position = new UI.Vector3() + .onChange(function () { + component.setPosition(position.getValue()) + }) + + // Rotation + + var q = new NGL.Quaternion() + var e = new NGL.Euler() + var rotation = new UI.Vector3() + .setRange(-6.28, 6.28) + .onChange(function () { + e.setFromVector3(rotation.getValue()) + q.setFromEuler(e) + component.setRotation(q) + }) + + // Scale + + var scale = new UI.Number(1) + .setRange(0.01, 100) + .onChange(function () { + component.setScale(scale.getValue()) + }) + + // Matrix + + signals.matrixChanged.add(function () { + position.setValue(component.position) + rotation.setValue(e.setFromQuaternion(component.quaternion)) + scale.setValue(component.scale.x) + }) + + // Component panel + + var componentPanel = new UI.ComponentPanel(component) + .setDisplay('inline-block') + .setMargin('0px') + .addMenuEntry('PDB file', pdb) + .addMenuEntry('Representation', repr) + .addMenuEntry('Assembly', assembly) + .addMenuEntry('Superpose', superpose) + .addMenuEntry( + 'File', new UI.Text(component.structure.path) + .setMaxWidth('100px') + .setOverflow('auto') + // .setWordWrap( "break-word" ) + ) + .addMenuEntry('Trajectory', traj) + .addMenuEntry('Principal axes', alignAxes) + .addMenuEntry('Measurements', removeMeasurements) + .addMenuEntry('Annotations', annotationButtons) + .addMenuEntry('Validation', vali) + .addMenuEntry('Position', position) + .addMenuEntry('Rotation', rotation) + .addMenuEntry('Scale', scale) + + if (NGL.ListingDatasource && NGL.TrajectoryDatasource) { + componentPanel.addMenuEntry('Remote trajectory', remoteTraj) + } + + // Fill container + + container + .addStatic(componentPanel) + .add(trajContainer) + .add(reprContainer) + + return container +} + +NGL.SurfaceComponentWidget = function (component, stage) { + var signals = component.signals + var container = new UI.CollapsibleIconPanel('minus-square', 'plus-square') + + var reprContainer = new UI.Panel() + + signals.representationAdded.add(function (repr) { + reprContainer.add( + new NGL.RepresentationElementWidget(repr, stage) + ) + }) + + // Add representation + + var repr = new UI.Select() + .setColor('#444') + .setOptions((function () { + var reprOptions = { + '': '[ add ]', + 'surface': 'surface', + 'dot': 'dot' + } + return reprOptions + })()) + .onChange(function () { + component.addRepresentation(repr.getValue()) + repr.setValue('') + componentPanel.setMenuDisplay('none') + }) + + // Position + + var position = new UI.Vector3() + .onChange(function () { + component.setPosition(position.getValue()) + }) + + // Rotation + + var q = new NGL.Quaternion() + var e = new NGL.Euler() + var rotation = new UI.Vector3() + .setRange(-6.28, 6.28) + .onChange(function () { + e.setFromVector3(rotation.getValue()) + q.setFromEuler(e) + component.setRotation(q) + }) + + // Scale + + var scale = new UI.Number(1) + .setRange(0.01, 100) + .onChange(function () { + component.setScale(scale.getValue()) + }) + + // Matrix + + signals.matrixChanged.add(function () { + position.setValue(component.position) + rotation.setValue(e.setFromQuaternion(component.quaternion)) + scale.setValue(component.scale.x) + }) + + // Component panel + + var componentPanel = new UI.ComponentPanel(component) + .setDisplay('inline-block') + .setMargin('0px') + .addMenuEntry('Representation', repr) + .addMenuEntry( + 'File', new UI.Text(component.surface.path) + .setMaxWidth('100px') + .setWordWrap('break-word')) + .addMenuEntry('Position', position) + .addMenuEntry('Rotation', rotation) + .addMenuEntry('Scale', scale) + + // Fill container + + container + .addStatic(componentPanel) + .add(reprContainer) + + return container +} + +NGL.VolumeComponentWidget = function (component, stage) { + var signals = component.signals + var container = new UI.CollapsibleIconPanel('minus-square', 'plus-square') + + var reprContainer = new UI.Panel() + + signals.representationAdded.add(function (repr) { + reprContainer.add( + new NGL.RepresentationElementWidget(repr, stage) + ) + }) + + // Add representation + + var repr = new UI.Select() + .setColor('#444') + .setOptions((function () { + var reprOptions = { + '': '[ add ]', + 'surface': 'surface', + 'dot': 'dot', + 'slice': 'slice' + } + return reprOptions + })()) + .onChange(function () { + component.addRepresentation(repr.getValue()) + repr.setValue('') + componentPanel.setMenuDisplay('none') + }) + + // Position + + var position = new UI.Vector3() + .onChange(function () { + component.setPosition(position.getValue()) + }) + + // Rotation + + var q = new NGL.Quaternion() + var e = new NGL.Euler() + var rotation = new UI.Vector3() + .setRange(-6.28, 6.28) + .onChange(function () { + e.setFromVector3(rotation.getValue()) + q.setFromEuler(e) + component.setRotation(q) + }) + + // Scale + + var scale = new UI.Number(1) + .setRange(0.01, 100) + .onChange(function () { + component.setScale(scale.getValue()) + }) + + // Matrix + + signals.matrixChanged.add(function () { + position.setValue(component.position) + rotation.setValue(e.setFromQuaternion(component.quaternion)) + scale.setValue(component.scale.x) + }) + + // Component panel + + var componentPanel = new UI.ComponentPanel(component) + .setDisplay('inline-block') + .setMargin('0px') + .addMenuEntry('Representation', repr) + .addMenuEntry( + 'File', new UI.Text(component.volume.path) + .setMaxWidth('100px') + .setWordWrap('break-word')) + .addMenuEntry('Position', position) + .addMenuEntry('Rotation', rotation) + .addMenuEntry('Scale', scale) + + // Fill container + + container + .addStatic(componentPanel) + .add(reprContainer) + + return container +} + +NGL.ShapeComponentWidget = function (component, stage) { + var signals = component.signals + var container = new UI.CollapsibleIconPanel('minus-square', 'plus-square') + + var reprContainer = new UI.Panel() + + signals.representationAdded.add(function (repr) { + reprContainer.add( + new NGL.RepresentationElementWidget(repr, stage) + ) + }) + + // Add representation + + var repr = new UI.Select() + .setColor('#444') + .setOptions((function () { + var reprOptions = { + '': '[ add ]', + 'buffer': 'buffer' + } + return reprOptions + })()) + .onChange(function () { + component.addRepresentation(repr.getValue()) + repr.setValue('') + componentPanel.setMenuDisplay('none') + }) + + // Position + + var position = new UI.Vector3() + .onChange(function () { + component.setPosition(position.getValue()) + }) + + // Rotation + + var q = new NGL.Quaternion() + var e = new NGL.Euler() + var rotation = new UI.Vector3() + .setRange(-6.28, 6.28) + .onChange(function () { + e.setFromVector3(rotation.getValue()) + q.setFromEuler(e) + component.setRotation(q) + }) + + // Scale + + var scale = new UI.Number(1) + .setRange(0.01, 100) + .onChange(function () { + component.setScale(scale.getValue()) + }) + + // Matrix + + signals.matrixChanged.add(function () { + position.setValue(component.position) + rotation.setValue(e.setFromQuaternion(component.quaternion)) + scale.setValue(component.scale.x) + }) + + // Component panel + + var componentPanel = new UI.ComponentPanel(component) + .setDisplay('inline-block') + .setMargin('0px') + .addMenuEntry('Representation', repr) + .addMenuEntry( + 'File', new UI.Text(component.shape.path) + .setMaxWidth('100px') + .setWordWrap('break-word')) + .addMenuEntry('Position', position) + .addMenuEntry('Rotation', rotation) + .addMenuEntry('Scale', scale) + + // Fill container + + container + .addStatic(componentPanel) + .add(reprContainer) + + return container +} + +// Representation + +NGL.RepresentationElementWidget = function (element, stage) { + var signals = element.signals + + var container = new UI.CollapsibleIconPanel('minus-square', 'plus-square') + .setMarginLeft('20px') + + signals.visibilityChanged.add(function (value) { + toggle.setValue(value) + }) + + signals.nameChanged.add(function (value) { + name.setValue(value) + }) + + signals.disposed.add(function () { + menu.dispose() + container.dispose() + }) + + // Name + + var name = new UI.EllipsisText(element.name) + .setWidth('103px') + + // Actions + + var toggle = new UI.ToggleIcon(element.visible, 'eye', 'eye-slash') + .setTitle('hide/show') + .setCursor('pointer') + .setMarginLeft('25px') + .onClick(function () { + element.setVisibility(!element.visible) + }) + + var disposeIcon = new UI.DisposeIcon() + .setMarginLeft('10px') + .setDisposeFunction(function () { + element.dispose() + }) + + container + .addStatic(name) + .addStatic(toggle) + .addStatic(disposeIcon) + + // Selection + + if ((element.parent.type === 'structure' || + element.parent.type === 'trajectory') && + element.repr.selection && element.repr.selection.type === 'selection' + ) { + container.add( + new UI.SelectionPanel(element.repr.selection) + .setMarginLeft('20px') + .setInputWidth('194px') + ) + } + + // Menu + + var menu = new UI.PopupMenu('bars', 'Representation') + .setMarginLeft('45px') + .setEntryLabelWidth('190px') + + menu.addEntry('type', new UI.Text(element.repr.type)) + + // Parameters + + var repr = element.repr + var rp = repr.getParameters() + + Object.keys(repr.parameters).forEach(function (name) { + if (!repr.parameters[ name ]) return + var p = Object.assign({}, repr.parameters[ name ]) + p.value = rp[ name ] + if (p.label === undefined) p.label = name + var input = NGL.createParameterInput(p) + + if (!input) return + + signals.parametersChanged.add(function (params) { + if (typeof input.setValue === 'function') { + input.setValue(params[ name ]) + } + }) + + function setParam () { + var po = {} + po[ name ] = input.getValue() + element.setParameters(po) + stage.viewer.requestRender() + } + + var ua = navigator.userAgent + if (p.type === 'range' && !/Trident/.test(ua) && !/MSIE/.test(ua)) { + input.onInput(setParam) + } else { + input.onChange(setParam) + } + + menu.addEntry(name, input) + }) + + container + .addStatic(menu) + + return container +} + +// Trajectory + +NGL.TrajectoryElementWidget = function (element, stage) { + var signals = element.signals + var traj = element.trajectory + + var container = new UI.CollapsibleIconPanel('minus-square', 'plus-square') + .setMarginLeft('20px') + + signals.disposed.add(function () { + menu.dispose() + container.dispose() + }) + + var frameCount = new UI.Panel() + .setDisplay('inline') + .add(new UI.Icon('spinner') + .addClass('spin') + .setMarginRight('99px') + ) + + var frameTime = new UI.Panel() + .setMarginLeft('5px') + .setDisplay('inline') + + function setFrame (value) { + frame.setValue(value) + if (traj.deltaTime && value >= 0) { + var t = traj.getFrameTime(value) / 1000 + time.setValue(t.toFixed(9).replace(/\.?0+$/g, '') + 'ns') + } else { + time.setValue('') + } + frameRange.setValue(value) + frameCount.clear().add(frame.setWidth('40px')) + frameTime.clear().add(time.setWidth('90px')) + } + + function init (value) { + frame.setRange(-1, value - 1) + frameRange.setRange(-1, value - 1) + + setFrame(traj.currentFrame) + + if (element.parameters.defaultStep !== undefined) { + step.setValue(element.parameters.defaultStep) + } else { + // 1000 = n / step + step.setValue(Math.ceil((value + 1) / 100)) + } + + player.setParameters({step: step.getValue()}) + player.setParameters({end: value - 1}) + } + + signals.countChanged.add(init) + signals.frameChanged.add(setFrame) + + // Name + + var name = new UI.EllipsisText(element.parameters.name) + .setWidth('103px') + + signals.nameChanged.add(function (value) { + name.setValue(value) + }) + + container.addStatic(name) + container.addStatic(frameTime) + + // frames + + var frame = new UI.Integer(-1) + .setWidth('40px') + .setTextAlign('right') + .setMarginLeft('5px') + .setRange(-1, -1) + .onChange(function (e) { + traj.setFrame(frame.getValue()) + menu.setMenuDisplay('none') + }) + + var time = new UI.Text() + .setTextAlign('right') + .setWidth('90px') + + var step = new UI.Integer(1) + .setWidth('50px') + .setRange(1, 10000) + .onChange(function () { + player.setParameters({step: step.getValue()}) + }) + + var frameRow = new UI.Panel() + + var frameRange = new UI.Range(-1, -1, -1, 1) + .setWidth('147px') + .setMargin('0px') + .setPadding('0px') + .setBorder('0px') + .onInput(function (e) { + var value = frameRange.getValue() + + if (value === traj.currentFrame) { + return + } + + if (traj.player && traj.player.isRunning) { + traj.setPlayer() + traj.setFrame(value) + } else if (!traj.inProgress) { + traj.setFrame(value) + } + }) + + var interpolateType = new UI.Select() + .setColor('#444') + .setOptions({ + '': 'none', + 'linear': 'linear', + 'spline': 'spline' + }) + .setValue(element.parameters.defaultInterpolateType) + .onChange(function () { + player.setParameters({interpolateType: interpolateType.getValue()}) + }) + + var interpolateStep = new UI.Integer(element.parameters.defaultInterpolateStep) + .setWidth('30px') + .setRange(1, 50) + .onChange(function () { + player.setParameters({interpolateStep: interpolateStep.getValue()}) + }) + + var playDirection = new UI.Select() + .setColor('#444') + .setOptions({ + 'forward': 'forward', + 'backward': 'backward', + 'bounce': 'bounce' + }) + .setValue(element.parameters.defaultDirection) + .onChange(function () { + player.setParameters({direction: playDirection.getValue()}) + }) + + var playMode = new UI.Select() + .setColor('#444') + .setOptions({ + 'loop': 'loop', + 'once': 'once' + }) + .setValue(element.parameters.defaultMode) + .onChange(function () { + player.setParameters({mode: playMode.getValue()}) + }) + + // player + + var timeout = new UI.Integer(element.parameters.defaultTimeout) + .setWidth('30px') + .setRange(10, 1000) + .onChange(function () { + player.setParameters({timeout: timeout.getValue()}) + }) + + var player = new NGL.TrajectoryPlayer(traj, { + step: step.getValue(), + timeout: timeout.getValue(), + start: 0, + end: traj.frameCount - 1, + interpolateType: interpolateType.getValue(), + interpolateStep: interpolateStep.getValue(), + direction: playDirection.getValue(), + mode: playMode.getValue() + }) + traj.setPlayer(player) + + var playerButton = new UI.ToggleIcon(true, 'play', 'pause') + .setMarginRight('10px') + .setMarginLeft('20px') + .setCursor('pointer') + .setWidth('12px') + .setTitle('play') + .onClick(function () { + player.toggle() + }) + + player.signals.startedRunning.add(function () { + playerButton + .setTitle('pause') + .setValue(false) + }) + + player.signals.haltedRunning.add(function () { + playerButton + .setTitle('play') + .setValue(true) + }) + + frameRow.add(playerButton, frameRange, frameCount) + + // Selection + + container.add( + new UI.SelectionPanel(traj.selection) + .setMarginLeft('20px') + .setInputWidth('194px') + ) + + // Options + + var setCenterPbc = new UI.Checkbox(traj.centerPbc) + .onChange(function () { + element.setParameters({ + 'centerPbc': setCenterPbc.getValue() + }) + }) + + var setRemovePeriodicity = new UI.Checkbox(traj.removePeriodicity) + .onChange(function () { + element.setParameters({ + 'removePeriodicity': setRemovePeriodicity.getValue() + }) + }) + + var setRemovePbc = new UI.Checkbox(traj.removePbc) + .onChange(function () { + element.setParameters({ + 'removePbc': setRemovePbc.getValue() + }) + }) + + var setSuperpose = new UI.Checkbox(traj.superpose) + .onChange(function () { + element.setParameters({ + 'superpose': setSuperpose.getValue() + }) + }) + + var setDeltaTime = new UI.Number(traj.deltaTime) + .setWidth('55px') + .setRange(0, 1000000) + .onChange(function () { + element.setParameters({ + 'deltaTime': setDeltaTime.getValue() + }) + }) + + var setTimeOffset = new UI.Number(traj.timeOffset) + .setWidth('55px') + .setRange(0, 1000000000) + .onChange(function () { + element.setParameters({ + 'timeOffset': setTimeOffset.getValue() + }) + }) + + signals.parametersChanged.add(function (params) { + setCenterPbc.setValue(traj.centerPbc) + setRemovePeriodicity.setValue(traj.removePeriodicity) + setRemovePbc.setValue(traj.removePbc) + setSuperpose.setValue(traj.superpose) + setDeltaTime.setValue(traj.deltaTime) + setTimeOffset.setValue(traj.timeOffset) + traj.setFrame(frame.getValue()) + }) + + // Dispose + + var dispose = new UI.DisposeIcon() + .setDisposeFunction(function () { + element.parent.removeTrajectory(element) + }) + + // + + if (traj.frameCount) { + init(traj.frameCount) + } + + // Menu + + var menu = new UI.PopupMenu('bars', 'Trajectory') + .setMarginLeft('10px') + .setEntryLabelWidth('130px') + .addEntry('Center', setCenterPbc) + .addEntry('Remove Periodicity', setRemovePeriodicity) + .addEntry('Remove PBC', setRemovePbc) + .addEntry('Superpose', setSuperpose) + .addEntry('Step size', step) + .addEntry('Interpolation type', interpolateType) + .addEntry('Interpolation steps', interpolateStep) + .addEntry('Play timeout', timeout) + .addEntry('Play direction', playDirection) + .addEntry('Play mode', playMode) + .addEntry('Delta time [ps]', setDeltaTime) + .addEntry('Time offset [ps]', setTimeOffset) + .addEntry('File', + new UI.Text(traj.trajPath) + .setMaxWidth('100px') + .setWordWrap('break-word')) + .addEntry('Dispose', dispose) + + container + .addStatic(menu) + + container + .add(frameRow) + + return container +} + +// Listing + +NGL.DirectoryListingWidget = function (datasource, stage, heading, filter, callback) { + // from http://stackoverflow.com/a/20463021/1435042 + function fileSizeSI (a, b, c, d, e) { + return (b = Math, c = b.log, d = 1e3, e = c(a) / c(d) | 0, a / b.pow(d, e)).toFixed(2) + + String.fromCharCode(160) + (e ? 'kMGTPEZY'[--e] + 'B' : 'Bytes') + } + + function getFolderDict (path) { + path = path || '' + var options = { '': '' } + var full = [] + path.split('/').forEach(function (chunk) { + full.push(chunk) + options[ full.join('/') ] = chunk + }) + return options + } + + var container = new UI.OverlayPanel() + + var headingPanel = new UI.Panel() + .setBorderBottom('1px solid #555') + .setHeight('30px') + + var listingPanel = new UI.Panel() + .setMarginTop('10px') + .setMinHeight('100px') + .setMaxHeight('500px') + .setPaddingRight('15px') + .setOverflow('auto') + + var folderSelect = new UI.Select() + .setColor('#444') + .setMarginLeft('20px') + .setWidth('') + .setMaxWidth('200px') + .setOptions(getFolderDict()) + .onChange(function () { + datasource.getListing(folderSelect.getValue()) + .then(onListingLoaded) + }) + + heading = heading || 'Directoy listing' + + headingPanel.add(new UI.Text(heading)) + headingPanel.add(folderSelect) + headingPanel.add( + new UI.Icon('times') + .setCursor('pointer') + .setMarginLeft('20px') + .setFloat('right') + .onClick(function () { + container.dispose() + }) + ) + + container.add(headingPanel) + container.add(listingPanel) + + function onListingLoaded (listing) { + var folder = listing.path + var data = listing.data + + NGL.lastUsedDirectory = folder + listingPanel.clear() + + folderSelect + .setOptions(getFolderDict(folder)) + .setValue(folder) + + data.forEach(function (info) { + var ext = info.path.split('.').pop().toLowerCase() + if (filter && !info.dir && filter.indexOf(ext) === -1) { + return + } + + var icon, name + if (info.dir) { + icon = 'folder-o' + name = info.name + } else { + icon = 'file-o' + name = info.name + String.fromCharCode(160) + + '(' + fileSizeSI(info.size) + ')' + } + + var pathRow = new UI.Panel() + .setDisplay('block') + .setWhiteSpace('nowrap') + .add(new UI.Icon(icon).setWidth('20px')) + .add(new UI.Text(name)) + .onClick(function () { + if (info.dir) { + datasource.getListing(info.path) + .then(onListingLoaded) + } else { + callback(info) + } + }) + + if (info.restricted) { + pathRow.add(new UI.Icon('lock').setMarginLeft('5px')) + } + + listingPanel.add(pathRow) + }) + } + + datasource.getListing(NGL.lastUsedDirectory) + .then(onListingLoaded) + + return container +} diff --git a/examples/examples/js/lib/colorpicker.min.js b/examples/examples/js/lib/colorpicker.min.js new file mode 100644 index 000000000..fbbf7ab5f --- /dev/null +++ b/examples/examples/js/lib/colorpicker.min.js @@ -0,0 +1,14 @@ +if( typeof importScripts !== 'function' ){ +(function(w,l,r){function s(a,c){var d=c.getBoundingClientRect();return{x:Math.max(Math.min(a.clientX-d.left,c.clientWidth),0),y:Math.max(Math.min(a.clientY-d.top,c.clientHeight),0)}}function f(a,c,d){a=l.createElementNS("http://www.w3.org/2000/svg",a);for(var b in c)a.setAttribute(b,c[b]);Array.isArray(d)||(d=[d]);c=0;for(b=d[0]&&d.length||0;c
', +this.slideElement=a.getElementsByClassName("slide")[0],this.pickerElement=a.getElementsByClassName("picker")[0],this.slideIndicator=a.getElementsByClassName("slide-indicator")[0],this.pickerIndicator=a.getElementsByClassName("picker-indicator")[0],g.positionIndicators(this.slideIndicator,this.pickerIndicator,{x:0,y:0},{x:0,y:0}),this.callback=function(a,b,d,e,f){g.positionIndicators(this.slideIndicator,this.pickerIndicator,f,e);c(a,b,d)});this.slide_listener=x(this,this.slideElement,this.pickerElement); +this.picker_listener=y(this,this.pickerElement);d||this.fixIndicators(this.slideIndicator,this.pickerIndicator);a=t.cloneNode(!0);d=u.cloneNode(!0);var b=a.getElementsByTagName("defs")[0].firstChild,e=a.getElementsByTagName("rect")[0];b.id="gradient-hsv-"+n;e.setAttribute("fill","url(#"+b.id+")");b=d.getElementsByTagName("defs")[0];b=[b.firstChild,b.lastChild];e=d.getElementsByTagName("rect");b[0].id="gradient-black-"+n;b[1].id="gradient-white-"+n;e[0].setAttribute("fill","url(#"+b[1].id+")");e[1].setAttribute("fill", +"url(#"+b[0].id+")");this.slideElement.appendChild(a);this.pickerElement.appendChild(d);n++;p(this.slideElement,this.slide_listener);p(this.pickerElement,this.picker_listener)}function p(a,c){function d(a){e&&c(a)}function b(a){d(a);e=!1;l.removeEventListener("mouseup",b,!1);l.removeEventListener("mousemove",d,!1)}var e=!1;a.addEventListener("mousedown",function(a){e=!0;a.preventDefault();l.addEventListener("mouseup",b,!0);l.addEventListener("mousemove",d,!1)},!1)}function q(a,c,d,b){a.h=c.h%360; +a.s=c.s;a.v=c.v;c=k(a);var e={y:a.h*a.slideElement.offsetHeight/360,x:0},f=a.pickerElement.offsetHeight,f={x:a.s*a.pickerElement.offsetWidth,y:f-a.v*f};a.pickerElement.style.backgroundColor=k({h:a.h,s:1,v:1}).hex;a.callback&&a.callback(b||c.hex,{h:a.h,s:a.s,v:a.v},d||{r:c.r,g:c.g,b:c.b},f,e);return a}var u,t,v={xmlns:"http://www.w3.org/2000/svg",version:"1.1",width:"100%",height:"100%"};t=f("svg",v,[f("defs",{},f("linearGradient",{id:"gradient-hsv",x1:"0%",y1:"100%",x2:"0%",y2:"0%"},[f("stop",{offset:"0%", +"stop-color":"#FF0000","stop-opacity":"1"}),f("stop",{offset:"13%","stop-color":"#FF00FF","stop-opacity":"1"}),f("stop",{offset:"25%","stop-color":"#8000FF","stop-opacity":"1"}),f("stop",{offset:"38%","stop-color":"#0040FF","stop-opacity":"1"}),f("stop",{offset:"50%","stop-color":"#00FFFF","stop-opacity":"1"}),f("stop",{offset:"63%","stop-color":"#00FF40","stop-opacity":"1"}),f("stop",{offset:"75%","stop-color":"#0BED00","stop-opacity":"1"}),f("stop",{offset:"88%","stop-color":"#FFFF00","stop-opacity":"1"}), +f("stop",{offset:"100%","stop-color":"#FF0000","stop-opacity":"1"})])),f("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:"url(#gradient-hsv)"})]);u=f("svg",v,[f("defs",{},[f("linearGradient",{id:"gradient-black",x1:"0%",y1:"100%",x2:"0%",y2:"0%"},[f("stop",{offset:"0%","stop-color":"#000000","stop-opacity":"1"}),f("stop",{offset:"100%","stop-color":"#CC9A81","stop-opacity":"0"})]),f("linearGradient",{id:"gradient-white",x1:"0%",y1:"100%",x2:"100%",y2:"100%"},[f("stop",{offset:"0%","stop-color":"#FFFFFF", +"stop-opacity":"1"}),f("stop",{offset:"100%","stop-color":"#CC9A81","stop-opacity":"0"})])]),f("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:"url(#gradient-white)"}),f("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:"url(#gradient-black)"})]);var n=0;g.hsv2rgb=function(a){a=k(a);delete a.hex;return a};g.hsv2hex=function(a){return k(a).hex};g.rgb2hsv=m;g.rgb2hex=function(a){return k(m(a)).hex};g.hex2hsv=function(a){return m(g.hex2rgb(a))};g.hex2rgb=function(a){return{r:parseInt(a.substr(1, +2),16),g:parseInt(a.substr(3,2),16),b:parseInt(a.substr(5,2),16)}};g.prototype.setHsv=function(a){return q(this,a)};g.prototype.setRgb=function(a){return q(this,m(a),a)};g.prototype.setHex=function(a){return q(this,g.hex2hsv(a),r,a)};g.positionIndicators=function(a,c,d,b){d&&(a.style.top=d.y-a.offsetHeight/2+"px");b&&(c.style.top=b.y-c.offsetHeight/2+"px",c.style.left=b.x-c.offsetWidth/2+"px")};g.prototype.fixIndicators=function(a,c){p(a,this.slide_listener);p(c,this.picker_listener)};w.ColorPicker= +g})(window,window.document); +} \ No newline at end of file diff --git a/examples/examples/js/lib/signals.min.js b/examples/examples/js/lib/signals.min.js new file mode 100644 index 000000000..a4e36e8dc --- /dev/null +++ b/examples/examples/js/lib/signals.min.js @@ -0,0 +1,14 @@ +/* + + JS Signals + Released under the MIT license + Author: Miller Medeiros + Version: 1.0.0 - Build: 268 (2012/11/29 05:48 PM) +*/ +(function(i){function h(a,b,c,d,e){this._listener=b;this._isOnce=c;this.context=d;this._signal=a;this._priority=e||0}function g(a,b){if(typeof a!=="function")throw Error("listener is a required param of {fn}() and should be a Function.".replace("{fn}",b));}function e(){this._bindings=[];this._prevParams=null;var a=this;this.dispatch=function(){e.prototype.dispatch.apply(a,arguments)}}h.prototype={active:!0,params:null,execute:function(a){var b;this.active&&this._listener&&(a=this.params?this.params.concat(a): +a,b=this._listener.apply(this.context,a),this._isOnce&&this.detach());return b},detach:function(){return this.isBound()?this._signal.remove(this._listener,this.context):null},isBound:function(){return!!this._signal&&!!this._listener},isOnce:function(){return this._isOnce},getListener:function(){return this._listener},getSignal:function(){return this._signal},_destroy:function(){delete this._signal;delete this._listener;delete this.context},toString:function(){return"[SignalBinding isOnce:"+this._isOnce+ +", isBound:"+this.isBound()+", active:"+this.active+"]"}};e.prototype={VERSION:"1.0.0",memorize:!1,_shouldPropagate:!0,active:!0,_registerListener:function(a,b,c,d){var e=this._indexOfListener(a,c);if(e!==-1){if(a=this._bindings[e],a.isOnce()!==b)throw Error("You cannot add"+(b?"":"Once")+"() then add"+(!b?"":"Once")+"() the same listener without removing the relationship first.");}else a=new h(this,a,b,c,d),this._addBinding(a);this.memorize&&this._prevParams&&a.execute(this._prevParams);return a}, +_addBinding:function(a){var b=this._bindings.length;do--b;while(this._bindings[b]&&a._priority<=this._bindings[b]._priority);this._bindings.splice(b+1,0,a)},_indexOfListener:function(a,b){for(var c=this._bindings.length,d;c--;)if(d=this._bindings[c],d._listener===a&&d.context===b)return c;return-1},has:function(a,b){return this._indexOfListener(a,b)!==-1},add:function(a,b,c){g(a,"add");return this._registerListener(a,!1,b,c)},addOnce:function(a,b,c){g(a,"addOnce");return this._registerListener(a, +!0,b,c)},remove:function(a,b){g(a,"remove");var c=this._indexOfListener(a,b);c!==-1&&(this._bindings[c]._destroy(),this._bindings.splice(c,1));return a},removeAll:function(){for(var a=this._bindings.length;a--;)this._bindings[a]._destroy();this._bindings.length=0},getNumListeners:function(){return this._bindings.length},halt:function(){this._shouldPropagate=!1},dispatch:function(a){if(this.active){var b=Array.prototype.slice.call(arguments),c=this._bindings.length,d;if(this.memorize)this._prevParams= +b;if(c){d=this._bindings.slice();this._shouldPropagate=!0;do c--;while(d[c]&&this._shouldPropagate&&d[c].execute(b)!==!1)}}},forget:function(){this._prevParams=null},dispose:function(){this.removeAll();delete this._bindings;delete this._prevParams},toString:function(){return"[Signal active:"+this.active+" numListeners:"+this.getNumListeners()+"]"}};var f=e;f.Signal=e;typeof define==="function"&&define.amd?define(function(){return f}):typeof module!=="undefined"&&module.exports?module.exports=f:i.signals= +f})(this); \ No newline at end of file diff --git a/examples/examples/js/lib/tether.min.js b/examples/examples/js/lib/tether.min.js new file mode 100644 index 000000000..9d37fc03d --- /dev/null +++ b/examples/examples/js/lib/tether.min.js @@ -0,0 +1,3 @@ +if( typeof importScripts !== 'function' ){ +!function(t,e){"function"==typeof define&&define.amd?define(e):"object"==typeof exports?module.exports=e(require,exports,module):t.Tether=e()}(this,function(t,e,o){"use strict";function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function n(t){var e=getComputedStyle(t),o=e.position;if("fixed"===o)return t;for(var i=t;i=i.parentNode;){var n=void 0;try{n=getComputedStyle(i)}catch(r){}if("undefined"==typeof n||null===n)return i;var s=n.overflow,a=n.overflowX,f=n.overflowY;if(/(auto|scroll)/.test(s+f+a)&&("absolute"!==o||["relative","absolute","fixed"].indexOf(n.position)>=0))return i}return document.body}function r(t){var e=void 0;t===document?(e=document,t=document.documentElement):e=t.ownerDocument;var o=e.documentElement,i={},n=t.getBoundingClientRect();for(var r in n)i[r]=n[r];var s=x(e);return i.top-=s.top,i.left-=s.left,"undefined"==typeof i.width&&(i.width=document.body.scrollWidth-i.left-i.right),"undefined"==typeof i.height&&(i.height=document.body.scrollHeight-i.top-i.bottom),i.top=i.top-o.clientTop,i.left=i.left-o.clientLeft,i.right=e.body.clientWidth-i.width-i.left,i.bottom=e.body.clientHeight-i.height-i.top,i}function s(t){return t.offsetParent||document.documentElement}function a(){var t=document.createElement("div");t.style.width="100%",t.style.height="200px";var e=document.createElement("div");f(e.style,{position:"absolute",top:0,left:0,pointerEvents:"none",visibility:"hidden",width:"200px",height:"150px",overflow:"hidden"}),e.appendChild(t),document.body.appendChild(e);var o=t.offsetWidth;e.style.overflow="scroll";var i=t.offsetWidth;o===i&&(i=e.clientWidth),document.body.removeChild(e);var n=o-i;return{width:n,height:n}}function f(){var t=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],e=[];return Array.prototype.push.apply(e,arguments),e.slice(1).forEach(function(e){if(e)for(var o in e)({}).hasOwnProperty.call(e,o)&&(t[o]=e[o])}),t}function h(t,e){if("undefined"!=typeof t.classList)e.split(" ").forEach(function(e){e.trim()&&t.classList.remove(e)});else{var o=new RegExp("(^| )"+e.split(" ").join("|")+"( |$)","gi"),i=u(t).replace(o," ");p(t,i)}}function l(t,e){if("undefined"!=typeof t.classList)e.split(" ").forEach(function(e){e.trim()&&t.classList.add(e)});else{h(t,e);var o=u(t)+(" "+e);p(t,o)}}function d(t,e){if("undefined"!=typeof t.classList)return t.classList.contains(e);var o=u(t);return new RegExp("(^| )"+e+"( |$)","gi").test(o)}function u(t){return t.className instanceof SVGAnimatedString?t.className.baseVal:t.className}function p(t,e){t.setAttribute("class",e)}function c(t,e,o){o.forEach(function(o){-1===e.indexOf(o)&&d(t,o)&&h(t,o)}),e.forEach(function(e){d(t,e)||l(t,e)})}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function g(t,e){var o=arguments.length<=2||void 0===arguments[2]?1:arguments[2];return t+o>=e&&e>=t-o}function m(){return"undefined"!=typeof performance&&"undefined"!=typeof performance.now?performance.now():+new Date}function v(){for(var t={top:0,left:0},e=arguments.length,o=Array(e),i=0;e>i;i++)o[i]=arguments[i];return o.forEach(function(e){var o=e.top,i=e.left;"string"==typeof o&&(o=parseFloat(o,10)),"string"==typeof i&&(i=parseFloat(i,10)),t.top+=o,t.left+=i}),t}function y(t,e){return"string"==typeof t.left&&-1!==t.left.indexOf("%")&&(t.left=parseFloat(t.left,10)/100*e.width),"string"==typeof t.top&&-1!==t.top.indexOf("%")&&(t.top=parseFloat(t.top,10)/100*e.height),t}function b(t,e){return"scrollParent"===e?e=t.scrollParent:"window"===e&&(e=[pageXOffset,pageYOffset,innerWidth+pageXOffset,innerHeight+pageYOffset]),e===document&&(e=e.documentElement),"undefined"!=typeof e.nodeType&&!function(){var t=r(e),o=t,i=getComputedStyle(e);e=[o.left,o.top,t.width+o.left,t.height+o.top],U.forEach(function(t,o){t=t[0].toUpperCase()+t.substr(1),"Top"===t||"Left"===t?e[o]+=parseFloat(i["border"+t+"Width"]):e[o]-=parseFloat(i["border"+t+"Width"])})}(),e}var w=function(){function t(t,e){for(var o=0;o1?a-1:0),h=1;a>h;h++)f[h-1]=arguments[h];i.apply(s,f),r?this.bindings[t].splice(e,1):++e}}}]),t}();C.Utils={getScrollParent:n,getBounds:r,getOffsetParent:s,extend:f,addClass:l,removeClass:h,hasClass:d,updateClasses:c,defer:T,flush:S,uniqueId:O,Evented:W,getScrollBarSize:a};var M=function(){function t(t,e){var o=[],i=!0,n=!1,r=void 0;try{for(var s,a=t[Symbol.iterator]();!(i=(s=a.next()).done)&&(o.push(s.value),!e||o.length!==e);i=!0);}catch(f){n=!0,r=f}finally{try{!i&&a["return"]&&a["return"]()}finally{if(n)throw r}}return o}return function(e,o){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,o);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),w=function(){function t(t,e){for(var o=0;o16?(e=Math.min(e-16,250),void(o=setTimeout(n,250))):void("undefined"!=typeof t&&m()-t<10||("undefined"!=typeof o&&(clearTimeout(o),o=null),t=m(),_(),e=m()-t))};["resize","scroll","touchmove"].forEach(function(t){window.addEventListener(t,i)})}();var z={center:"center",left:"right",right:"left"},F={middle:"middle",top:"bottom",bottom:"top"},L={top:0,left:0,middle:"50%",center:"50%",bottom:"100%",right:"100%"},Y=function(t,e){var o=t.left,i=t.top;return"auto"===o&&(o=z[e.left]),"auto"===i&&(i=F[e.top]),{left:o,top:i}},H=function(t){var e=t.left,o=t.top;return"undefined"!=typeof L[t.left]&&(e=L[t.left]),"undefined"!=typeof L[t.top]&&(o=L[t.top]),{left:e,top:o}},X=function(t){var e=t.split(" "),o=M(e,2),i=o[0],n=o[1];return{top:i,left:n}},j=X,N=function(){function t(e){var o=this;i(this,t),this.position=this.position.bind(this),B.push(this),this.history=[],this.setOptions(e,!1),C.modules.forEach(function(t){"undefined"!=typeof t.initialize&&t.initialize.call(o)}),this.position()}return w(t,[{key:"getClass",value:function(){var t=arguments.length<=0||void 0===arguments[0]?"":arguments[0],e=this.options.classes;return"undefined"!=typeof e&&e[t]?this.options.classes[t]:this.options.classPrefix?this.options.classPrefix+"-"+t:t}},{key:"setOptions",value:function(t){var e=this,o=arguments.length<=1||void 0===arguments[1]?!0:arguments[1],i={offset:"0 0",targetOffset:"0 0",targetAttachment:"auto auto",classPrefix:"tether"};this.options=f(i,t);var r=this.options,s=r.element,a=r.target,h=r.targetModifier;if(this.element=s,this.target=a,this.targetModifier=h,"viewport"===this.target?(this.target=document.body,this.targetModifier="visible"):"scroll-handle"===this.target&&(this.target=document.body,this.targetModifier="scroll-handle"),["element","target"].forEach(function(t){if("undefined"==typeof e[t])throw new Error("Tether Error: Both element and target must be defined");"undefined"!=typeof e[t].jquery?e[t]=e[t][0]:"string"==typeof e[t]&&(e[t]=document.querySelector(e[t]))}),l(this.element,this.getClass("element")),this.options.addTargetClasses!==!1&&l(this.target,this.getClass("target")),!this.options.attachment)throw new Error("Tether Error: You must provide an attachment");this.targetAttachment=j(this.options.targetAttachment),this.attachment=j(this.options.attachment),this.offset=X(this.options.offset),this.targetOffset=X(this.options.targetOffset),"undefined"!=typeof this.scrollParent&&this.disable(),this.scrollParent="scroll-handle"===this.targetModifier?this.target:n(this.target),this.options.enabled!==!1&&this.enable(o)}},{key:"getTargetBounds",value:function(){if("undefined"==typeof this.targetModifier)return r(this.target);if("visible"===this.targetModifier){if(this.target===document.body)return{top:pageYOffset,left:pageXOffset,height:innerHeight,width:innerWidth};var t=r(this.target),e={height:t.height,width:t.width,top:t.top,left:t.left};return e.height=Math.min(e.height,t.height-(pageYOffset-t.top)),e.height=Math.min(e.height,t.height-(t.top+t.height-(pageYOffset+innerHeight))),e.height=Math.min(innerHeight,e.height),e.height-=2,e.width=Math.min(e.width,t.width-(pageXOffset-t.left)),e.width=Math.min(e.width,t.width-(t.left+t.width-(pageXOffset+innerWidth))),e.width=Math.min(innerWidth,e.width),e.width-=2,e.topo.clientWidth||[i.overflow,i.overflowX].indexOf("scroll")>=0||this.target!==document.body,s=0;n&&(s=15);var a=t.height-parseFloat(i.borderTopWidth)-parseFloat(i.borderBottomWidth)-s,e={width:15,height:.975*a*(a/o.scrollHeight),left:t.left+t.width-parseFloat(i.borderLeftWidth)-15},f=0;408>a&&this.target===document.body&&(f=-11e-5*Math.pow(a,2)-.00727*a+22.58),this.target!==document.body&&(e.height=Math.max(e.height,24));var h=this.target.scrollTop/(o.scrollHeight-a);return e.top=h*(a-e.height-f)+t.top+parseFloat(i.borderTopWidth),this.target===document.body&&(e.height=Math.max(e.height,24)),e}}},{key:"clearCache",value:function(){this._cache={}}},{key:"cache",value:function(t,e){return"undefined"==typeof this._cache&&(this._cache={}),"undefined"==typeof this._cache[t]&&(this._cache[t]=e.call(this)),this._cache[t]}},{key:"enable",value:function(){var t=arguments.length<=0||void 0===arguments[0]?!0:arguments[0];this.options.addTargetClasses!==!1&&l(this.target,this.getClass("enabled")),l(this.element,this.getClass("enabled")),this.enabled=!0,this.scrollParent!==document&&this.scrollParent.addEventListener("scroll",this.position),t&&this.position()}},{key:"disable",value:function(){h(this.target,this.getClass("enabled")),h(this.element,this.getClass("enabled")),this.enabled=!1,"undefined"!=typeof this.scrollParent&&this.scrollParent.removeEventListener("scroll",this.position)}},{key:"destroy",value:function(){var t=this;this.disable(),B.forEach(function(e,o){return e===t?void B.splice(o,1):void 0})}},{key:"updateAttachClasses",value:function(t,e){var o=this;t=t||this.attachment,e=e||this.targetAttachment;var i=["left","top","bottom","right","middle","center"];"undefined"!=typeof this._addAttachClasses&&this._addAttachClasses.length&&this._addAttachClasses.splice(0,this._addAttachClasses.length),"undefined"==typeof this._addAttachClasses&&(this._addAttachClasses=[]);var n=this._addAttachClasses;t.top&&n.push(this.getClass("element-attached")+"-"+t.top),t.left&&n.push(this.getClass("element-attached")+"-"+t.left),e.top&&n.push(this.getClass("target-attached")+"-"+e.top),e.left&&n.push(this.getClass("target-attached")+"-"+e.left);var r=[];i.forEach(function(t){r.push(o.getClass("element-attached")+"-"+t),r.push(o.getClass("target-attached")+"-"+t)}),T(function(){"undefined"!=typeof o._addAttachClasses&&(c(o.element,o._addAttachClasses,r),o.options.addTargetClasses!==!1&&c(o.target,o._addAttachClasses,r),delete o._addAttachClasses)})}},{key:"position",value:function(){var t=this,e=arguments.length<=0||void 0===arguments[0]?!0:arguments[0];if(this.enabled){this.clearCache();var o=Y(this.targetAttachment,this.attachment);this.updateAttachClasses(this.attachment,o);var i=this.cache("element-bounds",function(){return r(t.element)}),n=i.width,f=i.height;if(0===n&&0===f&&"undefined"!=typeof this.lastSize){var h=this.lastSize;n=h.width,f=h.height}else this.lastSize={width:n,height:f};var l=this.cache("target-bounds",function(){return t.getTargetBounds()}),d=l,u=y(H(this.attachment),{width:n,height:f}),p=y(H(o),d),c=y(this.offset,{width:n,height:f}),g=y(this.targetOffset,d);u=v(u,c),p=v(p,g);for(var m=l.left+p.left-u.left,b=l.top+p.top-u.top,w=0;wwindow.innerWidth&&(A=this.cache("scrollbar-size",a),x.viewport.bottom-=A.height),document.body.scrollHeight>window.innerHeight&&(A=this.cache("scrollbar-size",a),x.viewport.right-=A.width),(-1===["","static"].indexOf(document.body.style.position)||-1===["","static"].indexOf(document.body.parentElement.style.position))&&(x.page.bottom=document.body.scrollHeight-b-f,x.page.right=document.body.scrollWidth-m-n),"undefined"!=typeof this.options.optimizations&&this.options.optimizations.moveElement!==!1&&"undefined"==typeof this.targetModifier&&!function(){var e=t.cache("target-offsetparent",function(){return s(t.target)}),o=t.cache("target-offsetparent-bounds",function(){return r(e)}),i=getComputedStyle(e),n=o,a={};if(["Top","Left","Bottom","Right"].forEach(function(t){a[t.toLowerCase()]=parseFloat(i["border"+t+"Width"])}),o.right=document.body.scrollWidth-o.left-n.width+a.right,o.bottom=document.body.scrollHeight-o.top-n.height+a.bottom,x.page.top>=o.top+a.top&&x.page.bottom>=o.bottom&&x.page.left>=o.left+a.left&&x.page.right>=o.right){var f=e.scrollTop,h=e.scrollLeft;x.offset={top:x.page.top-o.top+f-a.top,left:x.page.left-o.left+h-a.left}}}(),this.move(x),this.history.unshift(x),this.history.length>3&&this.history.pop(),e&&S(),!0}}},{key:"move",value:function(t){var e=this;if("undefined"!=typeof this.element.parentNode){var o={};for(var i in t){o[i]={};for(var n in t[i]){for(var r=!1,a=0;a=0&&(b=parseFloat(b),y=parseFloat(y)),b!==y&&(v=!0,m[n]=y)}v&&T(function(){f(e.element.style,m)})}}}]),t}();N.modules=[],C.position=_;var R=f(N,C),M=function(){function t(t,e){var o=[],i=!0,n=!1,r=void 0;try{for(var s,a=t[Symbol.iterator]();!(i=(s=a.next()).done)&&(o.push(s.value),!e||o.length!==e);i=!0);}catch(f){n=!0,r=f}finally{try{!i&&a["return"]&&a["return"]()}finally{if(n)throw r}}return o}return function(e,o){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,o);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),P=C.Utils,r=P.getBounds,f=P.extend,c=P.updateClasses,T=P.defer,U=["left","top","right","bottom"];C.modules.push({position:function(t){var e=this,o=t.top,i=t.left,n=t.targetAttachment;if(!this.options.constraints)return!0;var s=this.cache("element-bounds",function(){return r(e.element)}),a=s.height,h=s.width;if(0===h&&0===a&&"undefined"!=typeof this.lastSize){var l=this.lastSize;h=l.width,a=l.height}var d=this.cache("target-bounds",function(){return e.getTargetBounds()}),u=d.height,p=d.width,g=[this.getClass("pinned"),this.getClass("out-of-bounds")];this.options.constraints.forEach(function(t){var e=t.outOfBoundsClass,o=t.pinnedClass;e&&g.push(e),o&&g.push(o)}),g.forEach(function(t){["left","top","right","bottom"].forEach(function(e){g.push(t+"-"+e)})});var m=[],v=f({},n),y=f({},this.attachment);return this.options.constraints.forEach(function(t){var r=t.to,s=t.attachment,f=t.pin;"undefined"==typeof s&&(s="");var l=void 0,d=void 0;if(s.indexOf(" ")>=0){var c=s.split(" "),g=M(c,2);d=g[0],l=g[1]}else l=d=s;var w=b(e,r);("target"===d||"both"===d)&&(ow[3]&&"bottom"===v.top&&(o-=u,v.top="top")),"together"===d&&(ow[3]&&"bottom"===v.top&&("top"===y.top?(o-=u,v.top="top",o-=a,y.top="bottom"):"bottom"===y.top&&(o-=u,v.top="top",o+=a,y.top="top")),"middle"===v.top&&(o+a>w[3]&&"top"===y.top?(o-=a,y.top="bottom"):ow[2]&&"right"===v.left&&(i-=p,v.left="left")),"together"===l&&(iw[2]&&"right"===v.left?"left"===y.left?(i-=p,v.left="left",i-=h,y.left="right"):"right"===y.left&&(i-=p,v.left="left",i+=h,y.left="left"):"center"===v.left&&(i+h>w[2]&&"left"===y.left?(i-=h,y.left="right"):iw[3]&&"top"===y.top&&(o-=a,y.top="bottom")),("element"===l||"both"===l)&&(iw[2]&&"left"===y.left&&(i-=h,y.left="right")),"string"==typeof f?f=f.split(",").map(function(t){return t.trim()}):f===!0&&(f=["top","left","right","bottom"]),f=f||[];var C=[],O=[];o=0?(o=w[1],C.push("top")):O.push("top")),o+a>w[3]&&(f.indexOf("bottom")>=0?(o=w[3]-a,C.push("bottom")):O.push("bottom")),i=0?(i=w[0],C.push("left")):O.push("left")),i+h>w[2]&&(f.indexOf("right")>=0?(i=w[2]-h,C.push("right")):O.push("right")),C.length&&!function(){var t=void 0;t="undefined"!=typeof e.options.pinnedClass?e.options.pinnedClass:e.getClass("pinned"),m.push(t),C.forEach(function(e){m.push(t+"-"+e)})}(),O.length&&!function(){var t=void 0;t="undefined"!=typeof e.options.outOfBoundsClass?e.options.outOfBoundsClass:e.getClass("out-of-bounds"),m.push(t),O.forEach(function(e){m.push(t+"-"+e)})}(),(C.indexOf("left")>=0||C.indexOf("right")>=0)&&(y.left=v.left=!1),(C.indexOf("top")>=0||C.indexOf("bottom")>=0)&&(y.top=v.top=!1),(v.top!==n.top||v.left!==n.left||y.top!==e.attachment.top||y.left!==e.attachment.left)&&e.updateAttachClasses(y,v)}),T(function(){e.options.addTargetClasses!==!1&&c(e.target,m,g),c(e.element,m,g)}),{top:o,left:i}}});var P=C.Utils,r=P.getBounds,c=P.updateClasses,T=P.defer;C.modules.push({position:function(t){var e=this,o=t.top,i=t.left,n=this.cache("element-bounds",function(){return r(e.element)}),s=n.height,a=n.width,f=this.getTargetBounds(),h=o+s,l=i+a,d=[];o<=f.bottom&&h>=f.top&&["left","right"].forEach(function(t){var e=f[t];(e===i||e===l)&&d.push(t)}),i<=f.right&&l>=f.left&&["top","bottom"].forEach(function(t){var e=f[t];(e===o||e===h)&&d.push(t)});var u=[],p=[],g=["left","top","right","bottom"];return u.push(this.getClass("abutted")),g.forEach(function(t){u.push(e.getClass("abutted")+"-"+t)}),d.length&&p.push(this.getClass("abutted")),d.forEach(function(t){p.push(e.getClass("abutted")+"-"+t)}),T(function(){e.options.addTargetClasses!==!1&&c(e.target,p,u),c(e.element,p,u)}),!0}});var M=function(){function t(t,e){var o=[],i=!0,n=!1,r=void 0;try{for(var s,a=t[Symbol.iterator]();!(i=(s=a.next()).done)&&(o.push(s.value),!e||o.length!==e);i=!0);}catch(f){n=!0,r=f}finally{try{!i&&a["return"]&&a["return"]()}finally{if(n)throw r}}return o}return function(e,o){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,o);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();return C.modules.push({position:function(t){var e=t.top,o=t.left;if(this.options.shift){var i=this.options.shift;"function"==typeof this.options.shift&&(i=this.options.shift.call(this,{top:e,left:o}));var n=void 0,r=void 0;if("string"==typeof i){i=i.split(" "),i[1]=i[1]||i[0];var s=M(i,2);n=s[0],r=s[1],n=parseFloat(n,10),r=parseFloat(r,10)}else n=i.top,r=i.left;return e+=n,o+=r,{top:e,left:o}}}}),R}); +} \ No newline at end of file diff --git a/examples/examples/js/ui/ui.extra.js b/examples/examples/js/ui/ui.extra.js new file mode 100644 index 000000000..602c27602 --- /dev/null +++ b/examples/examples/js/ui/ui.extra.js @@ -0,0 +1,1136 @@ +/** + * @author Alexander Rose + */ + +// Html + +UI.Html = function (html) { + UI.Element.call(this) + + var dom = document.createElement('span') + dom.className = 'Html' + dom.style.cursor = 'default' + dom.style.display = 'inline-block' + dom.style.verticalAlign = 'middle' + + this.dom = dom + this.setValue(html) + + return this +} + +UI.Html.prototype = Object.create(UI.Element.prototype) + +UI.Html.prototype.setValue = function (value) { + if (value !== undefined) { + this.dom.innerHTML = value + } + + return this +} + +// Form + +UI.Form = function () { + UI.Panel.call(this) + + var dom = document.createElement('form') + dom.className = 'Form' + dom.method = 'post' + dom.action = '' + dom.target = '_blank' + dom.enctype = 'multipart/form-data' + + this.dom = dom + + return this +} + +UI.Form.prototype = Object.create(UI.Panel.prototype) + +UI.Form.prototype.setMethod = function (value) { + this.dom.method = value + + return this +} + +UI.Form.prototype.setAction = function (value) { + this.dom.action = value + + return this +} + +UI.Form.prototype.setTarget = function (value) { + this.dom.target = value + + return this +} + +UI.Form.prototype.setEnctype = function (value) { + this.dom.enctype = value + + return this +} + +// File + +UI.File = function () { + UI.Input.call(this) + + this.dom.className = 'File' + this.dom.type = 'file' + this.dom.multiple = false + + return this +} + +UI.File.prototype = Object.create(UI.Input.prototype) + +UI.File.prototype.setMultiple = function (value) { + this.dom.multiple = value + + return this +} + +UI.File.prototype.getFiles = function (value) { + return this.dom.files +} + +// Hidden + +UI.Hidden = function () { + UI.Input.call(this) + + this.dom.type = 'hidden' + + return this +} + +UI.Hidden.prototype = Object.create(UI.Input.prototype) + +// Toggle Button + +UI.ToggleButton = function (labelA, labelB, callbackA, callbackB) { + UI.Button.call(this, labelB) + + var flag = true + + this.onClick(function () { + if (flag) { + flag = false + this.setLabel(labelA) + callbackB() + } else { + flag = true + this.setLabel(labelB) + callbackA() + } + }.bind(this)) + + return this +} + +UI.ToggleButton.prototype = Object.create(UI.Button.prototype) + +// Ellipsis Text + +UI.EllipsisText = function (text) { + UI.Text.call(this, text) + + this.setWhiteSpace('nowrap') + this.setOverflow('hidden') + this.setTextOverflow('ellipsis') + + return this +} + +UI.EllipsisText.prototype = Object.create(UI.Text.prototype) + +UI.EllipsisText.prototype.setValue = function (value) { + if (value !== undefined) { + this.dom.textContent = value + this.setTitle(value) + } + + return this +} + +// Ellipsis Multiline Text + +UI.EllipsisMultilineText = function (text) { + // http://www.mobify.com/blog/multiline-ellipsis-in-pure-css/ + + UI.Element.call(this) + + var dom = document.createElement('span') + dom.className = 'EllipsisMultilineText' + dom.style.cursor = 'default' + dom.style.display = 'inline-block' + dom.style.verticalAlign = 'middle' + + var content = document.createElement('p') + dom.appendChild(content) + + this.dom = dom + this.content = content + + this.setValue(text) + + return this +} + +UI.EllipsisMultilineText.prototype = Object.create(UI.Element.prototype) + +UI.EllipsisMultilineText.prototype.setValue = function (value) { + if (value !== undefined) { + this.content.textContent = value + this.setTitle(value) + } + + return this +} + +// Overlay Panel + +UI.OverlayPanel = function () { + UI.Panel.call(this) + + this.dom.className = 'Panel OverlayPanel' + this.dom.tabIndex = '-1' + this.dom.style.outline = 'none' + + return this +} + +UI.OverlayPanel.prototype = Object.create(UI.Panel.prototype) + +UI.OverlayPanel.prototype.attach = function (node) { + node = node || document.body + + node.appendChild(this.dom) + + return this +} + +// Icon (requires font awesome) + +UI.Icon = function (value) { + UI.Panel.call(this) + + var dom = document.createElement('span') + dom.className = 'Icon fa' + + this.dom = dom + + if (value) this.addClass.apply(this, arguments) + + return this +} + +UI.Icon.prototype = Object.create(UI.Panel.prototype) + +UI.Icon.prototype.hasClass = function (value) { + return this.dom.classList.contains('fa-' + value) +} + +UI.Icon.prototype.addClass = function (value) { + for (var i = 0; i < arguments.length; i++) { + this.dom.classList.add('fa-' + arguments[ i ]) + } + + return this +} + +UI.Icon.prototype.setClass = function (value) { + this.dom.className = 'Icon fa' + + for (var i = 0; i < arguments.length; i++) { + this.dom.classList.add('fa-' + arguments[ i ]) + } + + return this +} + +UI.Icon.prototype.removeClass = function (value) { + for (var i = 0; i < arguments.length; i++) { + this.dom.classList.remove('fa-' + arguments[ i ]) + } + + return this +} + +UI.Icon.prototype.switchClass = function (newValue, oldValue) { + this.removeClass(oldValue, newValue) + this.addClass(newValue) + + return this +} + +// Toggle Icon + +UI.ToggleIcon = function (value, classTrue, classFalse) { + UI.Icon.call(this, value ? classTrue : classFalse) + + this.value = value + this.classTrue = classTrue + this.classFalse = classFalse + + return this +} + +UI.ToggleIcon.prototype = Object.create(UI.Icon.prototype) + +UI.ToggleIcon.prototype.setValue = function (value) { + this.value = value + + if (value) { + this.switchClass(this.classTrue, this.classFalse) + } else { + this.switchClass(this.classFalse, this.classTrue) + } + + return this +} + +UI.ToggleIcon.prototype.getValue = function () { + return this.value +} + +// Dispose Icon + +UI.DisposeIcon = function () { + UI.Icon.call(this, 'trash-o') + + var flag = false + var scope = this + + this.setTitle('delete') + this.setCursor('pointer') + + this.onClick(function () { + if (flag === true) { + if (typeof scope.disposeFunction === 'function') { + scope.disposeFunction() + } + } else { + scope.setColor('rgb(178, 34, 34)') + scope.dom.classList.add('deleteInfo') + flag = true + + setTimeout(function () { + scope.setColor('#888') + scope.dom.classList.remove('deleteInfo') + flag = false + }, 1500) + } + }) + + return this +} + +UI.DisposeIcon.prototype = Object.create(UI.Icon.prototype) + +UI.DisposeIcon.prototype.setDisposeFunction = function (fn) { + this.disposeFunction = fn + + return this +} + +// Progress + +UI.Progress = function (max, value) { + UI.Element.call(this) + + var dom = document.createElement('progress') + dom.className = 'Progress' + + dom.max = max || 1.0 + if (value !== undefined) dom.value = value + + this.dom = dom + + return this +} + +UI.Progress.prototype = Object.create(UI.Element.prototype) + +UI.Progress.prototype.getValue = function () { + return this.dom.value +} + +UI.Progress.prototype.setValue = function (value) { + this.dom.value = value + + return this +} + +UI.Progress.prototype.setMax = function (value) { + this.dom.max = value + + return this +} + +UI.Progress.prototype.setIndeterminate = function () { + this.dom.removeAttribute('value') + + return this +} + +// Range + +UI.Range = function (min, max, value, step) { + UI.Element.call(this) + + var dom = document.createElement('input') + dom.className = 'Range' + dom.type = 'range' + + dom.min = min.toPrecision(3) + dom.max = max.toPrecision(3) + dom.value = value.toPrecision(3) + dom.step = step.toPrecision(3) + + this.dom = dom + + return this +} + +UI.Range.prototype = Object.create(UI.Element.prototype) + +UI.Range.prototype.getValue = function () { + return parseFloat(this.dom.value) +} + +UI.Range.prototype.setRange = function (min, max) { + this.dom.min = min + this.dom.max = max + + return this +} + +UI.Range.prototype.setValue = function (value) { + this.dom.value = value + + return this +} + +UI.Range.prototype.setStep = function (value) { + this.dom.step = value + + return this +} + +// AdaptiveTextArea + +UI.AdaptiveTextArea = function () { + // http://www.brianchu.com/blog/2013/11/02/creating-an-auto-growing-text-input/ + + UI.Element.call(this) + + var container = document.createElement('div') + container.className = 'AdaptiveTextAreaContainer' + + var textarea = document.createElement('textarea') + textarea.className = 'AdaptiveTextArea' + + var size = document.createElement('div') + size.className = 'AdaptiveTextAreaSize' + + container.appendChild(textarea) + container.appendChild(size) + + textarea.addEventListener('input', function (event) { + size.innerHTML = textarea.value + '\n' + }, false) + + this.textarea = textarea + this.size = size + this.dom = container + + return this +} + +UI.AdaptiveTextArea.prototype = Object.create(UI.Element.prototype) + +UI.AdaptiveTextArea.prototype.getValue = function () { + return this.textarea.value +} + +UI.AdaptiveTextArea.prototype.setValue = function (value) { + this.textarea.value = value + this.size.innerHTML = value + '\n' + + return this +} + +UI.AdaptiveTextArea.prototype.setSpellcheck = function (value) { + this.textarea.spellcheck = value + + return this +} + +UI.AdaptiveTextArea.prototype.setBackgroundColor = function (value) { + this.textarea.style.backgroundColor = value + + return this +} + +// Virtual List + +UI.VirtualList = function (items, itemHeight, height, generatorFn) { + // based on Virtual DOM List + // https://github.com/sergi/virtual-list + // The MIT License (MIT) + // Copyright (C) 2013 Sergi Mansilla + + UI.Element.call(this) + + items = items || [] + itemHeight = itemHeight || 20 + height = height || 300 + generatorFn = generatorFn || function () {} + + var dom = document.createElement('div') + dom.className = 'VirtualList' + dom.style.height = height + 'px' + + var totalRows = items.length + var screenItemsCount = Math.ceil(height / itemHeight) + var cachedItemsCount = screenItemsCount * 3 + var lastRepaintY + var maxBuffer = screenItemsCount * itemHeight + var lastScrolled = 0 + var renderChunkCallback = function () {} + + var list = document.createElement('div') + list.style.width = '100%' + list.style.height = height + 'px' + list.style[ 'overflow-y' ] = 'auto' + list.style.position = 'relative' + list.style.padding = 0 + + var scroller = document.createElement('div') + scroller.style.opacity = 0 + scroller.style.position = 'absolute' + scroller.style.top = 0 + scroller.style.left = 0 + scroller.style.width = '1px' + scroller.style.height = (itemHeight * totalRows) + 'px' + + function createRow (i) { + var item = generatorFn(i) + item.classList.add('VirtualListRow') + item.style.height = itemHeight + 'px' + item.style.top = (i * itemHeight) + 'px' + return item + } + + function renderChunk (from) { + var finalItem = Math.min(totalRows, from + cachedItemsCount) + renderChunkCallback(from, finalItem) + // Append all the new rows in a document fragment + // that we will later append to the parent node + var fragment = document.createDocumentFragment() + for (var i = from; i < finalItem; i++) { + fragment.appendChild(createRow(i)) + } + // Hide and mark obsolete nodes for deletion. + for (var j = 1, l = list.childNodes.length; j < l; j++) { + list.childNodes[ j ].style.display = 'none' + list.childNodes[ j ].setAttribute('data-rm', '1') + } + list.appendChild(fragment) + }; + + // As soon as scrolling has stopped, this interval asynchronously + // removes all the nodes that are not used anymore + var rmNodeInterval = setInterval(function () { + // check if list is still attached to dom + var element = dom + while (element !== document && element.parentNode) { + element = element.parentNode + } + // if list not attached to dom, clear interval + if (element !== document) { + clearInterval(rmNodeInterval) + } + // remove tagged nodes + if (Date.now() - lastScrolled > 100) { + var badNodes = list.querySelectorAll('[data-rm="1"]') + for (var i = 0, l = badNodes.length; i < l; i++) { + list.removeChild(badNodes[ i ]) + } + } + }, 500) + + function onScroll (e) { + var scrollTop = e.target.scrollTop // Triggers reflow + if (!lastRepaintY || Math.abs(scrollTop - lastRepaintY) > maxBuffer) { + var first = Math.floor(scrollTop / itemHeight) + renderChunk(Math.max(0, first - screenItemsCount)) + lastRepaintY = scrollTop + } + lastScrolled = Date.now() + e.preventDefault && e.preventDefault() + } + + // API + + this.setItems = function (value) { + items = value + totalRows = items.length + scroller.style.height = (itemHeight * totalRows) + 'px' + renderChunk(0) + return this + } + + this.setItemHeight = function (value) { + itemHeight = value + screenItemsCount = Math.ceil(height / itemHeight) + cachedItemsCount = screenItemsCount * 3 + maxBuffer = screenItemsCount * itemHeight + scroller.style.height = (itemHeight * totalRows) + 'px' + renderChunk(0) + return this + } + + this.setHeight = function (value) { + UI.Element.prototype.setHeight.call(this, value + 'px') + height = value + screenItemsCount = Math.ceil(height / itemHeight) + cachedItemsCount = screenItemsCount * 3 + maxBuffer = screenItemsCount * itemHeight + list.style.height = height + 'px' + scroller.style.height = height + 'px' + renderChunk(0) + return this + } + + this.setGeneratorFn = function (value) { + generatorFn = value + renderChunk(0) + return this + } + + this.setRenderChunkCallback = function (value) { + renderChunkCallback = value + } + + this.redraw = function () { + var first = Math.floor(list.scrollTop / itemHeight) + renderChunk(Math.max(0, first - screenItemsCount)) + lastRepaintY = list.scrollTop + return this + } + + // + + list.appendChild(scroller) + dom.appendChild(list) + list.addEventListener('scroll', onScroll) + renderChunk(0) + + this.dom = dom + + return this +} + +UI.VirtualList.prototype = Object.create(UI.Element.prototype) + +// Virtual Table + +UI.VirtualTable = function (items, itemHeight, height, columns, params) { + var p = params || {} + + UI.Panel.call(this) + + // this.setOverflow( "scroll" ); + + var defaultWidth = p.defaultWidth !== undefined ? p.defaultWidth : 30 + var defaultMargin = p.defaultMargin !== undefined ? p.defaultMargin : 5 + var defaultAlign = p.defaultAlign !== undefined ? p.defaultAlign : 'left' + var onRowSelect = p.onRowSelect + + // header + + var header = new UI.Panel() + .setWhiteSpace('nowrap') + .setDisplay('inline-block') + .setOverflow('') + .setWidth('100%') + + var fullWidth = 0 + + var selected = [] + + var numericalSort = function (a, b) { + return a - b + } + + var lexicalSort = function (a, b) { + return a.localeCompare(b) + } + + var sortColumn = function (idx, flag) { + var sort + if (typeof items[ 0 ][ idx ] === 'string') { + sort = lexicalSort + } else { + sort = numericalSort + } + items.sort(function (a, b) { + if (flag) { + return sort(b[ idx ], a[ idx ]) + } else { + return sort(a[ idx ], b[ idx ]) + } + }) + virtualList.redraw() + return this + } + + var selectRow = function (event, idx) { + selected.length = 0 + if (onRowSelect) onRowSelect(event, idx) + if (idx !== undefined) { + selected.push(items[ idx ][ 0 ]) + } + virtualList.redraw() + return this + } + + columns.forEach(function (col) { + var width = col.width || defaultWidth + var margin = col.margin || defaultMargin + + var text = new UI.EllipsisText() + .setValue(col.name) + .setWidth(width + 'px') + .setTextAlign(col.align || defaultAlign) + .setMarginLeft(margin + 'px') + .setMarginRight(margin + 'px') + .setCursor('pointer') + .onClick(function (e) { + var flag = col.__sortFlag === 'ASC' + sortColumn(col.index, flag) + if (flag) { + col.__sortFlag = 'DESC' + } else { + col.__sortFlag = 'ASC' + } + }) + + header.add(text) + + fullWidth += width + 2 * margin + }) + + // list + + var generatorFn = function (index) { + var panel = new UI.Panel() + + columns.forEach(function (col) { + var value = items[ index ][ col.index ] + if (col.format) value = col.format(value) + + var width = col.width || defaultWidth + var margin = col.margin || defaultMargin + + var element + if (typeof value === 'object') { + element = value + } else { + element = new UI.Text() + .setValue(value) + } + + element + .setWidth(width + 'px') + .setTextAlign(col.align || defaultAlign) + .setMarginLeft(margin + 'px') + .setMarginRight(margin + 'px') + .onClick(function (event) { + if (typeof col.onClick === 'function') { + col.onClick(event, index, value) + } + }) + .onMouseOver(function (event) { + if (typeof col.onMouseOver === 'function') { + col.onMouseOver(event, index, value) + } + }) + .onMouseOut(function (event) { + if (typeof col.onMouseOut === 'function') { + col.onMouseOut(event, index, value) + } + }) + + panel.add(element) + }) + + panel + .setCursor('pointer') + .onClick(function (event) { + selectRow(event, index) + }) + + if (selected.indexOf(items[ index ][ 0 ]) !== -1) { + panel.dom.classList.add('highlight') + } + + return panel.dom + } + + var virtualList = new UI.VirtualList( + items, itemHeight, height, generatorFn + ).setWidth((fullWidth + 20) + 'px') + + // + + this.add(header, virtualList) + + // API + + this.header = header + this.list = virtualList + this.sortColumn = sortColumn + this.selectRow = function (idx) { + selectRow(undefined, idx) + } + + return this +} + +UI.VirtualTable.prototype = Object.create(UI.Panel.prototype) + +// Popup Menu (requires Tether) + +UI.PopupMenu = function (iconClass, heading, constraintTo) { + constraintTo = constraintTo || 'scrollParent' + + UI.Panel.call(this) + + var entryLabelWidth = '100px' + + var icon = new UI.Icon(iconClass || 'bars') + + var panel = new UI.OverlayPanel() + .setDisplay('none') + .attach(this.dom) + + var xOffset = 0 + var yOffset = 0 + + var prevX = 0 + var prevY = 0 + + function onMousemove (e) { + if (prevX === 0) { + prevX = e.clientX + prevY = e.clientY + } + xOffset += prevX - e.clientX + yOffset += prevY - e.clientY + prevX = e.clientX + prevY = e.clientY + tether.setOptions({ + element: panel.dom, + target: icon.dom, + attachment: 'top right', + targetAttachment: 'top left', + offset: yOffset + 'px ' + xOffset + 'px', + constraints: [{ + to: constraintTo, + pin: ['top', 'bottom'] + }] + }) + tether.position() + } + + var headingPanel = new UI.Panel() + .setBorderBottom('1px solid #555') + .setMarginBottom('10px') + .setHeight('25px') + .setCursor('move') + .onMouseDown(function (e) { + if (e.which === 1) { + document.addEventListener('mousemove', onMousemove) + } + document.addEventListener('mouseup', function (e) { + document.removeEventListener('mousemove', onMousemove) + }) + }) + + headingPanel + .add( + new UI.Icon('times') + .setFloat('right') + .setCursor('pointer') + .onClick(function () { + this.setMenuDisplay('none') + }.bind(this)) + ) + .add( + new UI.Text(heading) + ) + + panel.add(headingPanel) + + var tether + + icon.setTitle('menu') + icon.setCursor('pointer') + icon.onClick(function (e) { + if (panel.getDisplay() === 'block') { + this.setMenuDisplay('none') + tether.destroy() + return + } + + panel.setMaxHeight((window.innerHeight / 1.2) + 'px') + this.setMenuDisplay('block') + + xOffset = 5 + yOffset = 0 + + tether = new Tether({ + element: panel.dom, + target: icon.dom, + attachment: 'top right', + targetAttachment: 'top left', + offset: '0px 5px', + constraints: [{ + to: constraintTo, + attachment: 'element', + pin: ['top', 'bottom'] + }] + }) + + tether.position() + }.bind(this)) + + this.add(icon) + + this.setClass('') + .setDisplay('inline') + + this.icon = icon + this.panel = panel + this.entryLabelWidth = entryLabelWidth + + return this +} + +UI.PopupMenu.prototype = Object.create(UI.Panel.prototype) + +UI.PopupMenu.prototype.addEntry = function (label, entry) { + this.panel + .add(new UI.Text(label) + // .setWhiteSpace( "nowrap" ) + .setWidth(this.entryLabelWidth)) + .add(entry || new UI.Panel()) + .add(new UI.Break()) + + return this +} + +UI.PopupMenu.prototype.setEntryLabelWidth = function (value) { + this.entryLabelWidth = value + + return this +} + +UI.PopupMenu.prototype.setMenuDisplay = function (value) { + this.panel.setDisplay(value) + + if (value !== 'none') this.panel.dom.focus() + + return this +} + +UI.PopupMenu.prototype.setIconTitle = function (value) { + this.icon.setTitle(value) + + return this +} + +UI.PopupMenu.prototype.dispose = function () { + this.panel.dispose() + + UI.Element.prototype.dispose.call(this) +} + +// Collapsible Icon Panel + +UI.CollapsibleIconPanel = function (iconClass1, iconClass2) { + UI.Panel.call(this) + + this.dom.className = 'Panel CollapsiblePanel' + + if (iconClass1 === undefined) { + // iconClass1 = iconClass1 || "plus-square"; + // iconClass2 = iconClass2 || "minus-square"; + + iconClass1 = iconClass1 || 'chevron-down' + iconClass2 = iconClass2 || 'chevron-right' + } + + this.button = new UI.Icon(iconClass1) + .setTitle('expand/collapse') + .setCursor('pointer') + .setWidth('12px') + .setMarginRight('6px') + this.addStatic(this.button) + + var scope = this + this.button.dom.addEventListener('click', function (event) { + scope.toggle() + }, false) + + this.content = document.createElement('div') + this.content.className = 'CollapsibleContent' + this.dom.appendChild(this.content) + + this.isCollapsed = false + + this.iconClass1 = iconClass1 + this.iconClass2 = iconClass2 + + return this +} + +UI.CollapsibleIconPanel.prototype = Object.create(UI.CollapsiblePanel.prototype) + +UI.CollapsibleIconPanel.prototype.setCollapsed = function (setCollapsed) { + if (setCollapsed) { + this.dom.classList.add('collapsed') + + if (this.iconClass2) { + this.button.switchClass(this.iconClass2, this.iconClass1) + } else { + this.button.addClass('rotate-90') + } + } else { + this.dom.classList.remove('collapsed') + + if (this.iconClass2) { + this.button.switchClass(this.iconClass1, this.iconClass2) + } else { + this.button.removeClass('rotate-90') + } + } + + this.isCollapsed = setCollapsed +} + +// Color picker (requires FlexiColorPicker) +// https://github.com/DavidDurman/FlexiColorPicker +// https://github.com/zvin/FlexiColorPicker + +UI.ColorPicker = function () { + var scope = this + + UI.Panel.call(this) + + // slider + + this.slideWrapper = new UI.Panel() + .setClass('slide-wrapper') + + this.sliderIndicator = new UI.Panel() + .setClass('slide-indicator') + + this.slider = new UI.Panel() + .setClass('slide') + .setWidth('25px') + .setHeight('80px') + + this.slideWrapper.add( + this.slider, + this.sliderIndicator + ) + + // picker + + this.pickerWrapper = new UI.Panel() + .setClass('picker-wrapper') + + this.pickerIndicator = new UI.Panel() + .setClass('picker-indicator') + + this.picker = new UI.Panel() + .setClass('picker') + .setWidth('130px') + .setHeight('80px') + + this.pickerWrapper.add( + this.picker, + this.pickerIndicator + ) + + // event + + var changeEvent = document.createEvent('Event') + changeEvent.initEvent('change', true, true) + + // finalize + + this.add( + this.pickerWrapper, + this.slideWrapper + ) + + this.colorPicker = ColorPicker( + + this.slider.dom, + this.picker.dom, + + function (hex, hsv, rgb, pickerCoordinate, sliderCoordinate) { + if (!pickerCoordinate && sliderCoordinate && hsv.s < 0.05) { + hsv.s = 0.5 + hsv.v = 0.7 + scope.colorPicker.setHsv(hsv) + + return + } + + ColorPicker.positionIndicators( + scope.sliderIndicator.dom, scope.pickerIndicator.dom, + sliderCoordinate, pickerCoordinate + ) + + scope.hex = hex + scope.hsv = hsv + scope.rgb = rgb + + if (!scope._settingValue) { + scope.dom.dispatchEvent(changeEvent) + } + } + + ) + + this.colorPicker.fixIndicators( + this.sliderIndicator.dom, + this.pickerIndicator.dom + ) + + return this +} + +UI.ColorPicker.prototype = Object.create(UI.Panel.prototype) + +UI.ColorPicker.prototype.setValue = function (value) { + if (value !== this.hex) { + this._settingValue = true + this.colorPicker.setHex(value) + this._settingValue = false + } + + return this +} + +UI.ColorPicker.prototype.getValue = function () { + return this.hex +} diff --git a/examples/examples/js/ui/ui.js b/examples/examples/js/ui/ui.js new file mode 100644 index 000000000..241eca598 --- /dev/null +++ b/examples/examples/js/ui/ui.js @@ -0,0 +1,1037 @@ +/** + * @author mrdoob / http://mrdoob.com/ + * The MIT License, Copyright © 2010-2016 three.js authors + */ + +// TODO changes by Alexander S. Rose +// - more events and properties +// - ctrlKey modifier for Number and Integer +// - UI.Element.prototype.getBox() +// - UI.Element.prototype.dispose() +// - UI.Element.prototype.setTitle() +// - UI.Element.prototype.getStyle() + +var UI = {} + +UI.Element = function () {} + +UI.Element.prototype = { + + setId: function (id) { + this.dom.id = id + + return this + }, + + setTitle: function (title) { + this.dom.title = title + + return this + }, + + setClass: function (name) { + this.dom.className = name + + return this + }, + + setStyle: function (style, array) { + for (var i = 0; i < array.length; i++) { + this.dom.style[ style ] = array[ i ] + } + }, + + getStyle: function (style) { + return this.dom.style[ style ] + }, + + getBox: function () { + return this.dom.getBoundingClientRect() + }, + + setDisabled: function (value) { + this.dom.disabled = value + + return this + }, + + setTextContent: function (value) { + this.dom.textContent = value + + return this + }, + + dispose: function () { + this.dom.parentNode.removeChild(this.dom) + } + +} + +// properties + +var properties = [ + 'position', 'left', 'top', 'right', 'bottom', 'width', 'height', 'border', + 'borderLeft', 'borderTop', 'borderRight', 'borderBottom', 'borderColor', + 'display', 'overflow', 'overflowX', 'overflowY', 'margin', 'marginLeft', + 'marginTop', 'marginRight', + 'marginBottom', 'padding', 'paddingLeft', 'paddingTop', 'paddingRight', + 'paddingBottom', 'color', 'backgroundColor', 'opacity', 'fontSize', + 'fontWeight', 'fontStyle', 'fontFamily', 'textTransform', 'cursor', + 'verticalAlign', 'clear', 'float', 'zIndex', 'minHeight', 'maxHeight', + 'minWidth', 'maxWidth', 'wordBreak', 'wordWrap', 'spellcheck', + 'lineHeight', 'whiteSpace', 'textOverflow', 'textAlign', 'pointerEvents' +] + +properties.forEach(function (property) { + var methodSuffix = property.substr(0, 1).toUpperCase() + + property.substr(1, property.length) + + UI.Element.prototype[ 'set' + methodSuffix ] = function () { + this.setStyle(property, arguments) + return this + } + + UI.Element.prototype[ 'get' + methodSuffix ] = function () { + return this.getStyle(property) + } +}) + +// events + +var events = [ + 'KeyUp', 'KeyDown', 'KeyPress', + 'MouseOver', 'MouseOut', 'MouseDown', 'MouseUp', 'MouseMove', + 'Click', 'Change', 'Input', 'Scroll' +] + +events.forEach(function (event) { + var method = 'on' + event + + UI.Element.prototype[ method ] = function (callback) { + this.dom.addEventListener(event.toLowerCase(), callback.bind(this), false) + + return this + } +}) + +// Panel + +UI.Panel = function () { + UI.Element.call(this) + + var dom = document.createElement('div') + dom.className = 'Panel' + + this.dom = dom + this.children = [] + + return this +} + +UI.Panel.prototype = Object.create(UI.Element.prototype) + +UI.Panel.prototype.add = function () { + for (var i = 0; i < arguments.length; i++) { + this.dom.appendChild(arguments[ i ].dom) + this.children.push(arguments[ i ]) + } + + return this +} + +UI.Panel.prototype.remove = function () { + for (var i = 0; i < arguments.length; i++) { + this.dom.removeChild(arguments[ i ].dom) + + var idx = this.children.indexOf(arguments[ i ]) + if (idx !== -1) this.children.splice(idx, 1) + } + + return this +} + +UI.Panel.prototype.clear = function () { + while (this.dom.children.length) { + this.dom.removeChild(this.dom.lastChild) + } + + this.children.length = 0 + + return this +} + +// Collapsible Panel + +UI.CollapsiblePanel = function () { + UI.Panel.call(this) + + this.dom.className = 'Panel CollapsiblePanel' + + this.button = document.createElement('div') + this.button.className = 'CollapsiblePanelButton' + this.dom.appendChild(this.button) + + var scope = this + this.button.addEventListener('click', function (event) { + scope.toggle() + }, false) + + this.content = document.createElement('div') + this.content.className = 'CollapsibleContent' + this.dom.appendChild(this.content) + + this.isCollapsed = false + + return this +} + +UI.CollapsiblePanel.prototype = Object.create(UI.Panel.prototype) + +UI.CollapsiblePanel.prototype.addStatic = function () { + for (var i = 0; i < arguments.length; i++) { + this.dom.insertBefore(arguments[ i ].dom, this.content) + } + + return this +} + +UI.CollapsiblePanel.prototype.removeStatic = UI.Panel.prototype.remove + +UI.CollapsiblePanel.prototype.clearStatic = function () { + this.dom.childNodes.forEach(function (child) { + if (child !== this.content) { + this.dom.removeChild(child) + } + }) +} + +UI.CollapsiblePanel.prototype.add = function () { + for (var i = 0; i < arguments.length; i++) { + this.content.appendChild(arguments[ i ].dom) + } + + return this +} + +UI.CollapsiblePanel.prototype.remove = function () { + for (var i = 0; i < arguments.length; i++) { + this.content.removeChild(arguments[ i ].dom) + } + + return this +} + +UI.CollapsiblePanel.prototype.clear = function () { + while (this.content.children.length) { + this.content.removeChild(this.content.lastChild) + } +} + +UI.CollapsiblePanel.prototype.toggle = function () { + this.setCollapsed(!this.isCollapsed) +} + +UI.CollapsiblePanel.prototype.collapse = function () { + this.setCollapsed(true) +} + +UI.CollapsiblePanel.prototype.expand = function () { + this.setCollapsed(false) +} + +UI.CollapsiblePanel.prototype.setCollapsed = function (setCollapsed) { + if (setCollapsed) { + this.dom.classList.add('collapsed') + } else { + this.dom.classList.remove('collapsed') + } + + this.isCollapsed = setCollapsed +} + +// Text + +UI.Text = function (text) { + UI.Element.call(this) + + var dom = document.createElement('span') + dom.className = 'Text' + dom.style.display = 'inline-block' + dom.style.verticalAlign = 'middle' + + this.dom = dom + this.setValue(text) + + return this +} + +UI.Text.prototype = Object.create(UI.Element.prototype) + +UI.Text.prototype.setValue = function (value) { + if (value !== undefined) { + this.dom.textContent = value + } + + return this +} + +UI.Text.prototype.setName = function (value) { + this.dom.name = value + + return this +} +// Input + +UI.Input = function (value) { + UI.Element.call(this) + + var scope = this + + var dom = document.createElement('input') + dom.className = 'Input' + dom.style.padding = '2px' + dom.style.border = '1px solid #ccc' + + dom.addEventListener('keydown', function (event) { + event.stopPropagation() + }, false) + + this.dom = dom + this.setValue(value || '') + + return this +} + +UI.Input.prototype = Object.create(UI.Element.prototype) + +UI.Input.prototype.getValue = function () { + return this.dom.value +} + +UI.Input.prototype.setValue = function (value) { + this.dom.value = value + + return this +} + +UI.Input.prototype.setName = function (value) { + this.dom.name = value + + return this +} + +// TextArea + +UI.TextArea = function () { + UI.Element.call(this) + + var scope = this + + var dom = document.createElement('textarea') + dom.className = 'TextArea' + dom.style.padding = '2px' + dom.style.border = '1px solid #ccc' + + dom.addEventListener('keydown', function (event) { + event.stopPropagation() + }, false) + + this.dom = dom + + return this +} + +UI.TextArea.prototype = Object.create(UI.Element.prototype) + +UI.TextArea.prototype.getValue = function () { + return this.dom.value +} + +UI.TextArea.prototype.setValue = function (value) { + this.dom.value = value + + return this +} + +// Select + +UI.Select = function () { + UI.Element.call(this) + + var scope = this + + var dom = document.createElement('select') + dom.className = 'Select' + dom.style.width = '64px' + dom.style.height = '16px' + dom.style.border = '0px' + dom.style.padding = '0px' + + this.dom = dom + + return this +} + +UI.Select.prototype = Object.create(UI.Element.prototype) + +UI.Select.prototype.setMultiple = function (boolean) { + this.dom.multiple = boolean + + return this +} + +UI.Select.prototype.setOptions = function (options) { + var selected = this.dom.value + + while (this.dom.children.length > 0) { + this.dom.removeChild(this.dom.firstChild) + } + + for (var key in options) { + var option = document.createElement('option') + option.value = key + option.innerHTML = options[ key ] + this.dom.appendChild(option) + } + + this.dom.value = selected + + return this +} + +UI.Select.prototype.getValue = function () { + return this.dom.value +} + +UI.Select.prototype.setValue = function (value) { + this.dom.value = value + + return this +} + +UI.Select.prototype.setName = function (value) { + this.dom.name = value + + return this +} + +// FancySelect + +UI.FancySelect = function () { + UI.Element.call(this) + + var scope = this + + var dom = document.createElement('div') + dom.className = 'FancySelect' + dom.tabIndex = 0 // keyup event is ignored without setting tabIndex + + // Broadcast for object selection after arrow navigation + var changeEvent = document.createEvent('HTMLEvents') + changeEvent.initEvent('change', true, true) + + // Prevent native scroll behavior + dom.addEventListener('keydown', function (event) { + switch (event.keyCode) { + case 38: // up + case 40: // down + event.preventDefault() + event.stopPropagation() + break + } + }, false) + + // Keybindings to support arrow navigation + dom.addEventListener('keyup', function (event) { + switch (event.keyCode) { + case 38: // up + case 40: // down + scope.selectedIndex += (event.keyCode == 38) ? -1 : 1 + + if (scope.selectedIndex >= 0 && scope.selectedIndex < scope.options.length) { + // Highlight selected dom elem and scroll parent if needed + scope.setValue(scope.options[ scope.selectedIndex ].value) + + scope.dom.dispatchEvent(changeEvent) + } + + break + } + }, false) + + this.dom = dom + + this.options = [] + this.selectedIndex = -1 + this.selectedValue = null + + return this +} + +UI.FancySelect.prototype = Object.create(UI.Element.prototype) + +UI.FancySelect.prototype.setOptions = function (options) { + var scope = this + + var changeEvent = document.createEvent('HTMLEvents') + changeEvent.initEvent('change', true, true) + + while (scope.dom.children.length > 0) { + scope.dom.removeChild(scope.dom.firstChild) + } + + scope.options = [] + + for (var i = 0; i < options.length; i++) { + var option = options[ i ] + + var div = document.createElement('div') + div.className = 'option' + div.innerHTML = option.html + div.value = option.value + scope.dom.appendChild(div) + + scope.options.push(div) + + div.addEventListener('click', function (event) { + scope.setValue(this.value) + scope.dom.dispatchEvent(changeEvent) + }, false) + } + + return scope +} + +UI.FancySelect.prototype.getValue = function () { + return this.selectedValue +} + +UI.FancySelect.prototype.setValue = function (value) { + for (var i = 0; i < this.options.length; i++) { + var element = this.options[ i ] + + if (element.value === value) { + element.classList.add('active') + + // scroll into view + + var y = element.offsetTop - this.dom.offsetTop + var bottomY = y + element.offsetHeight + var minScroll = bottomY - this.dom.offsetHeight + + if (this.dom.scrollTop > y) { + this.dom.scrollTop = y + } else if (this.dom.scrollTop < minScroll) { + this.dom.scrollTop = minScroll + } + + this.selectedIndex = i + } else { + element.classList.remove('active') + } + } + + this.selectedValue = value + + return this +} + +// Checkbox + +UI.Checkbox = function (boolean) { + UI.Element.call(this) + + var scope = this + + var dom = document.createElement('input') + dom.className = 'Checkbox' + dom.type = 'checkbox' + + this.dom = dom + this.setValue(boolean) + + return this +} + +UI.Checkbox.prototype = Object.create(UI.Element.prototype) + +UI.Checkbox.prototype.getValue = function () { + return this.dom.checked +} + +UI.Checkbox.prototype.setValue = function (value) { + if (value !== undefined) { + this.dom.checked = value + } + + return this +} + +UI.Checkbox.prototype.setName = function (value) { + this.dom.name = value + + return this +} +// Color + +UI.Color = function () { + UI.Element.call(this) + + var scope = this + + var dom = document.createElement('input') + dom.className = 'Color' + dom.style.width = '64px' + dom.style.height = '16px' + dom.style.border = '0px' + dom.style.padding = '0px' + dom.style.backgroundColor = 'transparent' + + try { + dom.type = 'color' + dom.value = '#ffffff' + } catch (exception) {} + + this.dom = dom + + return this +} + +UI.Color.prototype = Object.create(UI.Element.prototype) + +UI.Color.prototype.getValue = function () { + return this.dom.value +} + +UI.Color.prototype.getHexValue = function () { + return parseInt(this.dom.value.substr(1), 16) +} + +UI.Color.prototype.setValue = function (value) { + this.dom.value = value + + return this +} + +UI.Color.prototype.setHexValue = function (hex) { + this.dom.value = '#' + ('000000' + hex.toString(16)).slice(-6) + + return this +} + +// Number + +UI.Number = function (number) { + UI.Element.call(this) + + var scope = this + + var dom = document.createElement('input') + dom.className = 'Number' + dom.value = '0.00' + + dom.addEventListener('keydown', function (event) { + event.stopPropagation() + + if (event.keyCode === 13) dom.blur() + }, false) + + this.min = -Infinity + this.max = Infinity + + this.precision = 2 + this.step = 1 + + this.dom = dom + this.setValue(number) + + var changeEvent = document.createEvent('HTMLEvents') + changeEvent.initEvent('change', true, true) + + var distance = 0 + var onMouseDownValue = 0 + + var pointer = [ 0, 0 ] + var prevPointer = [ 0, 0 ] + + var onMouseDown = function (event) { + event.preventDefault() + + distance = 0 + + onMouseDownValue = parseFloat(dom.value) + + prevPointer = [ event.clientX, event.clientY ] + + document.addEventListener('mousemove', onMouseMove, false) + document.addEventListener('mouseup', onMouseUp, false) + } + + var onMouseMove = function (event) { + var currentValue = dom.value + + pointer = [ event.clientX, event.clientY ] + + distance += (pointer[ 0 ] - prevPointer[ 0 ]) - (pointer[ 1 ] - prevPointer[ 1 ]) + + var modifier = 50 + if (event.shiftKey) modifier = 5 + if (event.ctrlKey) modifier = 500 + + var number = onMouseDownValue + (distance / modifier) * scope.step + + dom.value = Math.min(scope.max, Math.max(scope.min, number)).toFixed(scope.precision) + + if (currentValue !== dom.value) dom.dispatchEvent(changeEvent) + + prevPointer = [ event.clientX, event.clientY ] + } + + var onMouseUp = function (event) { + document.removeEventListener('mousemove', onMouseMove, false) + document.removeEventListener('mouseup', onMouseUp, false) + + if (Math.abs(distance) < 2) { + dom.focus() + dom.select() + } + } + + var onChange = function (event) { + var number = parseFloat(dom.value) + + dom.value = isNaN(number) === false ? number : 0 + } + + var onFocus = function (event) { + dom.style.backgroundColor = '' + dom.style.borderColor = '#ccc' + dom.style.cursor = '' + } + + var onBlur = function (event) { + dom.style.backgroundColor = 'transparent' + dom.style.borderColor = 'transparent' + dom.style.cursor = 'col-resize' + } + + dom.addEventListener('mousedown', onMouseDown, false) + dom.addEventListener('change', onChange, false) + dom.addEventListener('focus', onFocus, false) + dom.addEventListener('blur', onBlur, false) + + return this +} + +UI.Number.prototype = Object.create(UI.Element.prototype) + +UI.Number.prototype.getValue = function () { + return parseFloat(this.dom.value) +} + +UI.Number.prototype.setValue = function (value) { + if (isNaN(value)) { + this.dom.value = NaN + } else if (value !== undefined) { + this.dom.value = value.toFixed(this.precision) + } + + return this +} + +UI.Number.prototype.setRange = function (min, max) { + this.min = min + this.max = max + + return this +} + +UI.Number.prototype.setPrecision = function (precision) { + this.precision = precision + this.setValue(parseFloat(this.dom.value)) + + return this +} + +UI.Number.prototype.setName = function (value) { + this.dom.name = value + + return this +} +// Integer + +UI.Integer = function (number) { + UI.Element.call(this) + + var scope = this + + var dom = document.createElement('input') + dom.className = 'Number' + dom.value = '0.00' + + dom.addEventListener('keydown', function (event) { + event.stopPropagation() + }, false) + + this.min = -Infinity + this.max = Infinity + + this.step = 1 + + this.dom = dom + this.setValue(number) + + var changeEvent = document.createEvent('HTMLEvents') + changeEvent.initEvent('change', true, true) + + var distance = 0 + var onMouseDownValue = 0 + + var pointer = [ 0, 0 ] + var prevPointer = [ 0, 0 ] + + var onMouseDown = function (event) { + event.preventDefault() + + distance = 0 + + onMouseDownValue = parseFloat(dom.value) + + prevPointer = [ event.clientX, event.clientY ] + + document.addEventListener('mousemove', onMouseMove, false) + document.addEventListener('mouseup', onMouseUp, false) + } + + var onMouseMove = function (event) { + var currentValue = dom.value + + pointer = [ event.clientX, event.clientY ] + + distance += (pointer[ 0 ] - prevPointer[ 0 ]) - (pointer[ 1 ] - prevPointer[ 1 ]) + + var modifier = 50 + if (event.shiftKey) modifier = 5 + if (event.ctrlKey) modifier = 500 + + var number = onMouseDownValue + (distance / modifier) * scope.step + + dom.value = Math.min(scope.max, Math.max(scope.min, number)) | 0 + + if (currentValue !== dom.value) dom.dispatchEvent(changeEvent) + + prevPointer = [ event.clientX, event.clientY ] + } + + var onMouseUp = function (event) { + document.removeEventListener('mousemove', onMouseMove, false) + document.removeEventListener('mouseup', onMouseUp, false) + + if (Math.abs(distance) < 2) { + dom.focus() + dom.select() + } + } + + var onChange = function (event) { + var number = parseInt(dom.value) + + if (isNaN(number) === false) { + dom.value = number + } + } + + var onFocus = function (event) { + dom.style.backgroundColor = '' + dom.style.borderColor = '#ccc' + dom.style.cursor = '' + } + + var onBlur = function (event) { + dom.style.backgroundColor = 'transparent' + dom.style.borderColor = 'transparent' + dom.style.cursor = 'col-resize' + } + + dom.addEventListener('mousedown', onMouseDown, false) + dom.addEventListener('change', onChange, false) + dom.addEventListener('focus', onFocus, false) + dom.addEventListener('blur', onBlur, false) + + return this +} + +UI.Integer.prototype = Object.create(UI.Element.prototype) + +UI.Integer.prototype.getValue = function () { + return parseInt(this.dom.value) +} + +UI.Integer.prototype.setValue = function (value) { + if (value !== undefined) { + this.dom.value = value | 0 + } + + return this +} + +UI.Integer.prototype.setRange = function (min, max) { + this.min = min + this.max = max + + return this +} + +UI.Integer.prototype.setName = function (value) { + this.dom.name = value + + return this +} + +UI.Integer.prototype.setStep = function (step) { + this.step = step + + return this +} +// Break + +UI.Break = function () { + UI.Element.call(this) + + var dom = document.createElement('br') + dom.className = 'Break' + + this.dom = dom + + return this +} + +UI.Break.prototype = Object.create(UI.Element.prototype) + +// HorizontalRule + +UI.HorizontalRule = function () { + UI.Element.call(this) + + var dom = document.createElement('hr') + dom.className = 'HorizontalRule' + + this.dom = dom + + return this +} + +UI.HorizontalRule.prototype = Object.create(UI.Element.prototype) + +// Button + +UI.Button = function (value) { + UI.Element.call(this) + + var scope = this + + var dom = document.createElement('button') + dom.className = 'Button' + + this.dom = dom + this.dom.textContent = value + + return this +} + +UI.Button.prototype = Object.create(UI.Element.prototype) + +UI.Button.prototype.setLabel = function (value) { + this.dom.textContent = value + + return this +} + +// Helper + +UI.MenubarHelper = { + + createMenuContainer: function (name, optionsPanel) { + var container = new UI.Panel() + var title = new UI.Panel() + title.setClass('title') + + title.setTextContent(name) + title.setMargin('0px') + title.setPadding('8px') + + container.setClass('menu') + container.add(title) + container.add(optionsPanel) + + return container + }, + + createOption: function (name, callbackHandler, icon) { + var option = new UI.Panel() + option.setClass('option') + + if (icon) { + option.add(new UI.Icon(icon).setWidth('20px')) + option.add(new UI.Text(name)) + } else { + option.setTextContent(name) + } + + option.onClick(callbackHandler) + + return option + }, + + createOptionsPanel: function (menuConfig) { + var options = new UI.Panel() + options.setClass('options') + + menuConfig.forEach(function (option) { + options.add(option) + }) + + return options + }, + + createInput: function (name, callbackHandler) { + var panel = new UI.Panel() + .setClass('option') + + var text = new UI.Text() + .setWidth('70px') + .setValue(name) + + var input = new UI.Input() + .setWidth('40px') + .onKeyDown(callbackHandler) + + panel.add(text) + panel.add(input) + + return panel + }, + + createCheckbox: function (name, value, callbackHandler) { + var panel = new UI.Panel() + .setClass('option') + + var text = new UI.Text() + .setWidth('70px') + .setValue(name) + + var checkbox = new UI.Checkbox() + .setValue(value) + .onClick(callbackHandler) + + panel.add(checkbox) + panel.add(text) + + return panel + }, + + createDivider: function () { + return new UI.HorizontalRule() + } + +} diff --git a/examples/examples/js/ui/ui.ngl.js b/examples/examples/js/ui/ui.ngl.js new file mode 100644 index 000000000..59815338b --- /dev/null +++ b/examples/examples/js/ui/ui.ngl.js @@ -0,0 +1,368 @@ +/** + * @file UI NGL + * @author Alexander Rose + */ + +// Color + +UI.ColorPopupMenu = function () { + var scope = this + + UI.Panel.call(this) + + this.iconText = new UI.Text('') + .setCursor('pointer') + .setClass('fa-stack-1x') + .setFontFamily('Arial, sans-serif') + .setColor('#111') + + this.iconSquare = new UI.Icon('square', 'stack-1x') + // .setMarginTop( "0.05em" ); + + this.menu = new UI.PopupMenu('stack', 'Color') + + this.menu.icon + .setTitle('color') + .setWidth('1em').setHeight('1em').setLineHeight('1em') + .add(this.iconSquare) + .add(this.iconText) + + var changeEvent = document.createEvent('Event') + changeEvent.initEvent('change', true, true) + + this.colorInput = new UI.Input() + .onChange(function () { + scope.setColor(scope.colorInput.getValue()) + scope.dom.dispatchEvent(changeEvent) + }) + + this.colorPicker = new UI.ColorPicker() + .setDisplay('inline-block') + .onChange(function (e) { + scope.setColor(scope.colorPicker.getValue()) + scope.dom.dispatchEvent(changeEvent) + }) + + this.menu + .addEntry('Input', this.colorInput) + .addEntry('Picker', this.colorPicker) + + this.add(this.menu) + + this.setClass('') + .setDisplay('inline') + + return this +} + +UI.ColorPopupMenu.prototype = Object.create(UI.Panel.prototype) + +UI.ColorPopupMenu.prototype.setColor = (function () { + var c = new NGL.Color() + + return function (value) { + c.set(value) + value = '#' + c.getHexString() + + this.colorInput + .setBackgroundColor(value) + .setValue(value) + + this.colorPicker.setValue(value) + + this.iconSquare.setColor(value) + + // perceived brightness (http://alienryderflex.com/hsp.html) + var brightness = Math.sqrt( + c.r * 255 * c.r * 255 * 0.241 + + c.g * 255 * c.g * 255 * 0.691 + + c.b * 255 * c.b * 255 * 0.068 + ) + + if (brightness > 130) { + this.iconText.setColor('#000000') + this.colorInput.setColor('#000000') + } else { + this.iconText.setColor('#FFFFFF') + this.colorInput.setColor('#FFFFFF') + } + + return this + } +}()) + +UI.ColorPopupMenu.prototype.getColor = function () { + return this.colorInput.getValue() +} + +UI.ColorPopupMenu.prototype.getValue = function () { + return this.getColor() +} + +UI.ColorPopupMenu.prototype.setValue = function (value) { + this.setColor(value) + + return this +} + +UI.ColorPopupMenu.prototype.dispose = function () { + this.menu.dispose() + + UI.Panel.prototype.dispose.call(this) +} + +// Vector3 + +UI.Vector3 = function (value) { + UI.Panel.call(this).setDisplay('inline-block') + + this.xNumber = new UI.Number(0).setWidth('40px') + this.yNumber = new UI.Number(0).setWidth('40px') + this.zNumber = new UI.Number(0).setWidth('40px') + + this.add(this.xNumber, this.yNumber, this.zNumber) + this.setValue(value) + + var changeEvent = document.createEvent('Event') + changeEvent.initEvent('change', true, true) + + this.xNumber.onChange(function () { + this.dom.dispatchEvent(changeEvent) + }.bind(this)) + this.yNumber.onChange(function () { + this.dom.dispatchEvent(changeEvent) + }.bind(this)) + this.zNumber.onChange(function () { + this.dom.dispatchEvent(changeEvent) + }.bind(this)) + + return this +} + +UI.Vector3.prototype = Object.create(UI.Panel.prototype) + +UI.Vector3.prototype.getValue = function () { + return { + x: this.xNumber.getValue(), + y: this.yNumber.getValue(), + z: this.zNumber.getValue() + } +} + +UI.Vector3.prototype.setValue = function (value) { + if (value) { + this.xNumber.setValue(value.x) + this.yNumber.setValue(value.y) + this.zNumber.setValue(value.z) + } + + return this +} + +UI.Vector3.prototype.setPrecision = function (precision) { + this.xNumber.setPrecision(precision) + this.yNumber.setPrecision(precision) + this.zNumber.setPrecision(precision) + + return this +} + +UI.Vector3.prototype.setRange = function (min, max) { + this.xNumber.setRange(min, max) + this.yNumber.setRange(min, max) + this.zNumber.setRange(min, max) + + return this +} + +// Selection + +UI.SelectionInput = function (selection) { + UI.AdaptiveTextArea.call(this) + + this.setSpellcheck(false) + + if (!(selection.type === 'selection')) { + NGL.error('UI.SelectionInput: not a selection', selection) + + return this + } + + this.setValue(selection.string) + + this.selection = selection + + var scope = this + + var signals = selection.signals + + signals.stringChanged.add(function (string) { + scope.setValue(string) + }) + + this.onEnter() + + return this +} + +UI.SelectionInput.prototype = Object.create(UI.AdaptiveTextArea.prototype) + +UI.SelectionInput.prototype.setValue = function (value) { + UI.AdaptiveTextArea.prototype.setValue.call(this, value) + + return this +} + +UI.SelectionInput.prototype.onEnter = function (callback) { + // TODO more a private method + + var scope = this + + var check = function (string) { + var selection = new NGL.Selection(string) + + return !selection.selection[ 'error' ] + } + + this.onKeyPress(function (e) { + var value = scope.getValue() + var character = String.fromCharCode(e.which) + + if (e.keyCode === 13) { + e.preventDefault() + + if (check(value)) { + if (typeof callback === 'function') { + callback(value) + } else { + scope.selection.setString(value) + } + + scope.setBackgroundColor('white') + } else { + scope.setBackgroundColor('tomato') + } + } else if (scope.selection.string !== value + character) { + scope.setBackgroundColor('skyblue') + } else { + scope.setBackgroundColor('white') + } + }) + + this.onKeyUp(function (e) { + var value = scope.getValue() + + if (!check(value)) { + scope.setBackgroundColor('tomato') + } else if (scope.selection.string === scope.getValue()) { + scope.setBackgroundColor('white') + } else { + scope.setBackgroundColor('skyblue') + } + }) + + return this +} + +UI.SelectionPanel = function (selection) { + UI.Panel.call(this) + + this.icon = new UI.Icon('filter') + .setTitle('filter selection') + .addClass('lg') + .setMarginRight('10px') + + this.input = new UI.SelectionInput(selection) + + this.add(this.icon, this.input) + + return this +} + +UI.SelectionPanel.prototype = Object.create(UI.Panel.prototype) + +UI.SelectionPanel.prototype.setInputWidth = function (value) { + this.input.setWidth(value) + + return this +} + +// Component + +UI.ComponentPanel = function (component) { + UI.Panel.call(this) + + var stage = component.stage + var signals = component.signals + + signals.nameChanged.add(function (value) { + name.setValue(value) + }) + + signals.visibilityChanged.add(function (value) { + toggle.setValue(value) + }) + + signals.disposed.add(function () { + menu.dispose() + }) + + // Name + + var name = new UI.EllipsisText(component.name) + .setWidth('100px') + + // Actions + + var toggle = new UI.ToggleIcon(component.visible, 'eye', 'eye-slash') + .setTitle('hide/show') + .setCursor('pointer') + .setMarginLeft('25px') + .onClick(function () { + component.setVisibility(!component.visible) + }) + + var center = new UI.Icon('bullseye') + .setTitle('center') + .setCursor('pointer') + .setMarginLeft('10px') + .onClick(function () { + component.autoView(1000) + }) + + var dispose = new UI.DisposeIcon() + .setMarginLeft('10px') + .setDisposeFunction(function () { + stage.removeComponent(component) + }) + + // Menu + + var menu = new UI.PopupMenu('bars', component.type) + .setMarginLeft('46px') + .setEntryLabelWidth('110px') + + // + + this.add(name, toggle, center, dispose, menu) + + // + + this.menu = menu + + return this +} + +UI.ComponentPanel.prototype = Object.create(UI.Panel.prototype) + +UI.ComponentPanel.prototype.addMenuEntry = function (label, entry) { + this.menu.addEntry(label, entry) + + return this +} + +UI.ComponentPanel.prototype.setMenuDisplay = function (value) { + this.menu.setMenuDisplay(value) + + return this +} diff --git a/examples/examples/mobile.html b/examples/examples/mobile.html new file mode 100644 index 000000000..0ee385bcc --- /dev/null +++ b/examples/examples/mobile.html @@ -0,0 +1,56 @@ + + + + NGL - mobile + + + + + + + +
+
+
+ +
+
+ + diff --git a/examples/examples/parallel.html b/examples/examples/parallel.html new file mode 100644 index 000000000..4996ccc20 --- /dev/null +++ b/examples/examples/parallel.html @@ -0,0 +1,33 @@ + + + + NGL - parallel + + + + + + + +
+ + \ No newline at end of file diff --git a/examples/examples/scripts/color/atomindex.js b/examples/examples/scripts/color/atomindex.js new file mode 100644 index 000000000..a537a14b3 --- /dev/null +++ b/examples/examples/scripts/color/atomindex.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://1blu.mmtf').then(function (o) { + o.addRepresentation('ball+stick', { color: 'atomindex' }) + o.autoView() +}) diff --git a/examples/examples/scripts/color/bfactor.js b/examples/examples/scripts/color/bfactor.js new file mode 100644 index 000000000..7d5e8179e --- /dev/null +++ b/examples/examples/scripts/color/bfactor.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://1blu.mmtf').then(function (o) { + o.addRepresentation('cartoon', { color: 'bfactor' }) + o.autoView() +}) diff --git a/examples/examples/scripts/color/chainid.js b/examples/examples/scripts/color/chainid.js new file mode 100644 index 000000000..288964446 --- /dev/null +++ b/examples/examples/scripts/color/chainid.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://3SN6.cif').then(function (o) { + o.addRepresentation('cartoon', { color: 'chainid' }) + o.autoView() +}) diff --git a/examples/examples/scripts/color/custom.js b/examples/examples/scripts/color/custom.js new file mode 100644 index 000000000..f3dddcf5f --- /dev/null +++ b/examples/examples/scripts/color/custom.js @@ -0,0 +1,17 @@ + +var schemeId = NGL.ColormakerRegistry.addScheme(function (params) { + this.atomColor = function (atom) { + if (atom.serial < 1000) { + return 0x0000FF // blue + } else if (atom.serial > 2000) { + return 0xFF0000 // red + } else { + return 0x00FF00 // green + } + } +}) + +stage.loadFile('data://3dqb.pdb').then(function (o) { + o.addRepresentation('cartoon', { color: schemeId }) + o.autoView() +}) diff --git a/examples/examples/scripts/color/electrostatic.js b/examples/examples/scripts/color/electrostatic.js new file mode 100644 index 000000000..997abbfef --- /dev/null +++ b/examples/examples/scripts/color/electrostatic.js @@ -0,0 +1,9 @@ + +stage.loadFile('data://3dqb.pdb').then(function (o) { + o.addRepresentation('surface', { + sele: 'polymer', + colorScheme: 'electrostatic', + surfaceType: 'av' + }) + o.autoView() +}) diff --git a/examples/examples/scripts/color/element.js b/examples/examples/scripts/color/element.js new file mode 100644 index 000000000..7cb9c0d34 --- /dev/null +++ b/examples/examples/scripts/color/element.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://1blu.mmtf').then(function (o) { + o.addRepresentation('ball+stick', { color: 'element' }) + o.autoView() +}) diff --git a/examples/examples/scripts/color/modelindex.js b/examples/examples/scripts/color/modelindex.js new file mode 100644 index 000000000..47e5088fc --- /dev/null +++ b/examples/examples/scripts/color/modelindex.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://1LVZ.cif').then(function (o) { + o.addRepresentation('cartoon', { color: 'modelindex' }) + o.autoView() +}) diff --git a/examples/examples/scripts/color/partialcharge.js b/examples/examples/scripts/color/partialcharge.js new file mode 100644 index 000000000..3913cca3d --- /dev/null +++ b/examples/examples/scripts/color/partialcharge.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://adrenalin.mol2').then(function (o) { + o.addRepresentation('ball+stick', { color: 'partialCharge' }) + o.autoView() +}) diff --git a/examples/examples/scripts/color/resname.js b/examples/examples/scripts/color/resname.js new file mode 100644 index 000000000..7efd9704a --- /dev/null +++ b/examples/examples/scripts/color/resname.js @@ -0,0 +1,7 @@ + +stage.loadFile('data://1d66.pdb').then(function (o) { + o.addRepresentation('cartoon', { color: 'resname' }) + o.addRepresentation('base', { color: 'resname' }) + o.addRepresentation('ball+stick', { color: 'resname', visible: false }) + o.autoView() +}) diff --git a/examples/examples/scripts/color/selection.js b/examples/examples/scripts/color/selection.js new file mode 100644 index 000000000..6892b57be --- /dev/null +++ b/examples/examples/scripts/color/selection.js @@ -0,0 +1,25 @@ + +var schemeId = NGL.ColormakerRegistry.addSelectionScheme([ + [ + 'atomindex', + '64-74 or 134-154 or 222-254 or 310-310 or 322-326', + { scale: ['firebrick', 'red', 'orangered'] } + ], + [ 'green', '311-322' ], + [ + 'atomindex', + '40-63 or 75-95 or 112-133 or 155-173 or 202-221 or 255-277 or 289-309', + { scale: ['gold', 'yellow', 'lightyellow'] } + ], + [ + 'atomindex', + '1-39 or 96-112 or 174-201 or 278-288', + { scale: ['blue', 'dodgerblue', 'cyan'] } + ], + [ 'white', '*' ] +], 'TMDET 3dqb') + +stage.loadFile('data://3dqb.pdb').then(function (o) { + o.addRepresentation('cartoon', { color: schemeId }) + o.autoView() +}) diff --git a/examples/examples/scripts/color/sstruc.js b/examples/examples/scripts/color/sstruc.js new file mode 100644 index 000000000..0327ce9dc --- /dev/null +++ b/examples/examples/scripts/color/sstruc.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://1blu.mmtf').then(function (o) { + o.addRepresentation('cartoon', { color: 'sstruc' }) + o.autoView() +}) diff --git a/examples/examples/scripts/color/volume-esp.js b/examples/examples/scripts/color/volume-esp.js new file mode 100644 index 000000000..263a8ddc4 --- /dev/null +++ b/examples/examples/scripts/color/volume-esp.js @@ -0,0 +1,25 @@ + +Promise.all([ + stage.loadFile('data://hf.dx'), + stage.loadFile('data://esp.dx'), + stage.loadFile('data://esp.mol', { ext: 'sdf' }) +]).then(function (l) { + var hfComponent = l[ 0 ] + var espComponent = l[ 1 ] + var molComponent = l[ 2 ] + + molComponent.addRepresentation('licorice', { multipleBond: true }) + + hfComponent.addRepresentation('surface', + { isolevel: 0.002, + isolevelType: 'value', + opacity: 0.95, + side: 'front', + colorScheme: 'volume', + colorVolume: espComponent.volume, + colorScale: [ 0xff0000, 0xffff00, 0x00ff00, 0x00ffff, 0x0000ff ], + colorMode: 'rgb', + colorDomain: [ -0.05, 0.05 ] + }) + stage.autoView() +}) diff --git a/examples/examples/scripts/color/volume.js b/examples/examples/scripts/color/volume.js new file mode 100644 index 000000000..3960a0888 --- /dev/null +++ b/examples/examples/scripts/color/volume.js @@ -0,0 +1,27 @@ + +Promise.all([ + stage.loadFile('data://betaGal.mrc'), + stage.loadFile('data://localResolution.mrc', { voxelSize: 3.54 }) +]).then(function (l) { + var betaGal = l[ 0 ] + var localResolution = l[ 1 ] + betaGal.addRepresentation('surface', { + colorVolume: localResolution.volume, + colorScheme: 'volume', + colorScale: 'rwb', + colorReverse: true, + colorDomain: [ 5, 14 ] + }) + localResolution.addRepresentation('dot', { + thresholdMin: 0, + thresholdMax: 8, + thresholdType: 'value', + dotType: 'sphere', + radius: 0.6, + colorScheme: 'value', + colorScale: 'rwb', + colorReverse: true, + colorDomain: [ 5, 14 ] + }) + stage.autoView() +}) diff --git a/examples/examples/scripts/component/getByName.js b/examples/examples/scripts/component/getByName.js new file mode 100644 index 000000000..febe0cfbb --- /dev/null +++ b/examples/examples/scripts/component/getByName.js @@ -0,0 +1,12 @@ + +// name a loaded component and access it via `stage.getComponentsByName` + +stage.loadFile('data://1crn.pdb', { name: 'myProtein' }).then(function (o) { + o.autoView() + o.addRepresentation('cartoon') +}).then(function () { + stage.getComponentsByName('myProtein').addRepresentation('distance', { + atomPair: [ [ '10.CA', '25.CA' ] ], + color: 'skyblue' + }) +}) diff --git a/examples/examples/scripts/component/matrix.js b/examples/examples/scripts/component/matrix.js new file mode 100644 index 000000000..7bc8d2ec2 --- /dev/null +++ b/examples/examples/scripts/component/matrix.js @@ -0,0 +1,15 @@ + +// Load a protein +stage.loadFile('data://1crn.pdb').then(function (o) { + o.addRepresentation('cartoon') + stage.autoView() +}) + +// Load the same protein and move it +stage.loadFile('data://1crn.pdb').then(function (o) { + o.setPosition([ 20, 0, 0 ]) + o.setRotation([ 2, 0, 0 ]) + o.setScale(0.5) + o.addRepresentation('cartoon', { color: 'orange' }) + stage.autoView() +}) diff --git a/examples/examples/scripts/component/shape-buffer.js b/examples/examples/scripts/component/shape-buffer.js new file mode 100644 index 000000000..e5f3933cb --- /dev/null +++ b/examples/examples/scripts/component/shape-buffer.js @@ -0,0 +1,19 @@ + +var shape = new NGL.Shape('shape') +var sphereBuffer = new NGL.SphereBuffer({ + position: new Float32Array([ 0, 0, 0, 4, 0, 0 ]), + color: new Float32Array([ 1, 0, 0, 1, 1, 0 ]), + radius: new Float32Array([ 1, 1.2 ]) +}) +shape.addBuffer(sphereBuffer) +var boxBuffer = new NGL.BoxBuffer({ + position: new Float32Array([ 0, 3, 0, -2, 0, 0 ]), + color: new Float32Array([ 1, 0, 1, 0, 1, 0 ]), + size: new Float32Array([ 2, 1.5 ]), + heightAxis: new Float32Array([ 0, 1, 1, 0, 2, 0 ]), + depthAxis: new Float32Array([ 1, 0, 1, 0, 0, 2 ]) +}) +shape.addBuffer(boxBuffer) +var shapeComp = stage.addComponentFromObject(shape) +shapeComp.addRepresentation('buffer') +shapeComp.autoView() diff --git a/examples/examples/scripts/component/shape-cat.js b/examples/examples/scripts/component/shape-cat.js new file mode 100644 index 000000000..8def66081 --- /dev/null +++ b/examples/examples/scripts/component/shape-cat.js @@ -0,0 +1,32 @@ + +var grey = [ 0.8, 0.8, 0.8 ] +var darkgrey = [ 0.6, 0.6, 0.6 ] + +var shape = new NGL.Shape('shape', { + labelParams: { attachment: 'middle-center' }, + sphereDetail: 4, + radialSegments: 100 +}) +shape.addEllipsoid([ 0, 0, 0 ], grey, 4, [ 0, 3, 0 ], [ 0, 0, 1 ], 'Face') +shape.addSphere([ -2, 1, -1 ], darkgrey, 0.3, 'Right eye') +shape.addSphere([ 2, 1, -1 ], darkgrey, 0.3, 'Left eye') +shape.addSphere([ 0, 0, -1 ], darkgrey, 0.5, 'Nose') +shape.addEllipsoid([ -1, -1, -1 ], darkgrey, 1.3, [ 0, 1, 0 ], [ 0, 0, 0.3 ], 'Right cheek') +shape.addEllipsoid([ 1, -1, -1 ], darkgrey, 1.3, [ 0, 1, 0 ], [ 0, 0, 0.3 ], 'Left cheek') +shape.addCone([ 2.5, 1.7, 0 ], [ 4, 3, 0 ], darkgrey, 0.8, 'Left ear') +shape.addCone([ -2.5, 1.7, 0 ], [ -4, 3, 0 ], darkgrey, 0.8, 'Right ear') +shape.addCylinder([ -1, -1, -1 ], [ -4.3, -0.2, -1.2 ], darkgrey, 0.1, 'Whisker') +shape.addCylinder([ -1, -1, -1 ], [ -4.5, -1.2, -1.2 ], darkgrey, 0.1, 'Whisker') +shape.addCylinder([ -1, -1, -1 ], [ -4.2, -2.2, -1.2 ], darkgrey, 0.1, 'Whisker') +shape.addCylinder([ 1, -1, -1 ], [ 4.3, -0.2, -1.2 ], darkgrey, 0.1, 'Whisker') +shape.addCylinder([ 1, -1, -1 ], [ 4.5, -1.2, -1.2 ], darkgrey, 0.1, 'Whisker') +shape.addCylinder([ 1, -1, -1 ], [ 4.2, -2.2, -1.2 ], darkgrey, 0.1, 'Whisker') +shape.addText([ 0, 4, -1 ], [ 0.2, 0.5, 0.8 ], 2.5, 'Meow') + +var shapeComp = stage.addComponentFromObject(shape) +shapeComp.addRepresentation('buffer') +shapeComp.autoView() + +setTimeout(function () { + stage.setRock([ 0, 1, 0 ], 0.005, 0.3) +}, 1000) diff --git a/examples/examples/scripts/component/shape-wireframe.js b/examples/examples/scripts/component/shape-wireframe.js new file mode 100644 index 000000000..cd592077c --- /dev/null +++ b/examples/examples/scripts/component/shape-wireframe.js @@ -0,0 +1,8 @@ + +var shape = new NGL.Shape('shape', { disableImpostor: true, radialSegments: 10 }) +shape.addSphere([ -3.5, 2, 2 ], [ 1, 0.5, 0 ], 3) +shape.addArrow([ 2, 2, 7 ], [ 10, -3, -3 ], [ 1, 0.5, 1 ], 1.0) +shape.addText([ 0, -2, 0 ], [ 0.2, 0.5, 0.8 ], 2.5, 'wire-sphere') +var shapeComp = stage.addComponentFromObject(shape) +shapeComp.addRepresentation('buffer', { wireframe: true }) +stage.autoView() diff --git a/examples/examples/scripts/component/shape.js b/examples/examples/scripts/component/shape.js new file mode 100644 index 000000000..c5c70245f --- /dev/null +++ b/examples/examples/scripts/component/shape.js @@ -0,0 +1,23 @@ + +var shape = new NGL.Shape('shape', { dashedCylinder: true }) +shape.addMesh( + [ 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1 ], + [ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 ], + undefined, undefined, 'My mesh' +) +shape.addSphere([ 0, 0, 9 ], [ 1, 0, 0 ], 1.5) +shape.addSphere([ 12, 5, 15 ], [ 1, 0.5, 0 ], 1) +shape.addEllipsoid([ 6, 0, 0 ], [ 1, 0, 0 ], 1.5, [ 3, 0, 0 ], [ 0, 2, 0 ]) +shape.addCylinder([ 0, 2, 7 ], [ 0, 0, 9 ], [ 1, 1, 0 ], 0.5, 'My Cylinder') +shape.addCone([ 0, 2, 7 ], [ 0, 3, 3 ], [ 1, 1, 0 ], 1.5) +shape.addArrow([ 1, 2, 7 ], [ 30, 3, 3 ], [ 1, 0, 1 ], 1.0) +shape.addArrow([ 2, 2, 7 ], [ 30, -3, -3 ], [ 1, 0.5, 1 ], 1.0) +shape.addBox([ 23, 1, 2 ], [ 0, 1, 0 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]) +shape.addTetrahedron([ 27, 0, 1 ], [ 0, 1, 0 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]) +shape.addOctahedron([ 8, 5, 14 ], [ 0, 1, 0 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]) +shape.addTorus([ 16, 5, 14 ], [ 0, 1, 0 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]) +shape.addText([ 15, -4, 4 ], [ 0.2, 0.5, 0.8 ], 2.5, 'Hello') + +var shapeComp = stage.addComponentFromObject(shape) +shapeComp.addRepresentation('buffer') +shapeComp.autoView() diff --git a/examples/examples/scripts/component/structure-autoChainName.js b/examples/examples/scripts/component/structure-autoChainName.js new file mode 100644 index 000000000..76b0dc9ad --- /dev/null +++ b/examples/examples/scripts/component/structure-autoChainName.js @@ -0,0 +1,8 @@ + +stage.loadFile('data://Bace1Trimer-inDPPC.gro', { + sele: ':A or :B or DPPC' +}).then(function (o) { + o.addRepresentation('cartoon') + o.addRepresentation('licorice', { sele: 'DPPC' }) + o.autoView() +}) diff --git a/examples/examples/scripts/component/structure-biomol.js b/examples/examples/scripts/component/structure-biomol.js new file mode 100644 index 000000000..37950cdf3 --- /dev/null +++ b/examples/examples/scripts/component/structure-biomol.js @@ -0,0 +1,12 @@ + +console.time('load-to-render') +stage.loadFile('data://4opj.cif').then(function (o) { + o.addRepresentation('cartoon', { assembly: 'BU1', opacity: 0.5, side: 'back' }) + o.addRepresentation('ribbon', { assembly: 'SUPERCELL', color: 'grey', scale: 1.0, visible: false }) + o.addRepresentation('backbone', { assembly: 'AU' }) + o.addRepresentation('surface', { assembly: 'BU2' }) + stage.autoView() + stage.tasks.onZeroOnce(function () { + console.timeEnd('load-to-render') + }) +}) diff --git a/examples/examples/scripts/component/structure-biomolSimple.js b/examples/examples/scripts/component/structure-biomolSimple.js new file mode 100644 index 000000000..f8a0b0fb6 --- /dev/null +++ b/examples/examples/scripts/component/structure-biomolSimple.js @@ -0,0 +1,11 @@ + +stage.loadFile('data://1U19.cif').then(function (o) { + o.addRepresentation('licorice') + o.addRepresentation('cartoon', { + assembly: 'BU1', color: 0xFF1111 + }) + o.addRepresentation('cartoon', { + assembly: 'BU2', color: 0x11FF11 + }) + o.autoView() +}) diff --git a/examples/examples/scripts/component/structure-bondOrders.js b/examples/examples/scripts/component/structure-bondOrders.js new file mode 100644 index 000000000..aaa74cf81 --- /dev/null +++ b/examples/examples/scripts/component/structure-bondOrders.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://4umt_47w.sdf').then(function (o) { + o.addRepresentation('licorice', { multipleBond: 'symmetric' }) + stage.autoView() +}) diff --git a/examples/examples/scripts/component/structure-coarseGrained.js b/examples/examples/scripts/component/structure-coarseGrained.js new file mode 100644 index 000000000..2059fbea5 --- /dev/null +++ b/examples/examples/scripts/component/structure-coarseGrained.js @@ -0,0 +1,7 @@ + +stage.loadFile('data://BaceCg.pdb').then(function (o) { + o.addRepresentation('cartoon') + o.addRepresentation('rope', { sele: 'helix' }) + o.addRepresentation('ball+stick') + o.autoView() +}) diff --git a/examples/examples/scripts/component/structure-cyclic.js b/examples/examples/scripts/component/structure-cyclic.js new file mode 100644 index 000000000..bda4ef4b2 --- /dev/null +++ b/examples/examples/scripts/component/structure-cyclic.js @@ -0,0 +1,7 @@ + +stage.loadFile('data://1sfi.cif').then(function (o) { + o.addRepresentation('cartoon', { color: 'chainindex' }) + o.addRepresentation('backbone') + o.addRepresentation('trace', { linewidth: 3 }) + o.autoView() +}) diff --git a/examples/examples/scripts/component/structure-dna.js b/examples/examples/scripts/component/structure-dna.js new file mode 100644 index 000000000..6d404c844 --- /dev/null +++ b/examples/examples/scripts/component/structure-dna.js @@ -0,0 +1,14 @@ + +stage.loadFile('data://1d66.pdb').then(function (o) { + o.addRepresentation('cartoon', { + sele: 'nucleic', wireframe: false + }) + o.addRepresentation('base', { + sele: '*', color: 'resname' + }) + o.addRepresentation('licorice', { + sele: 'nucleic', color: 'element', visible: false + }) + + o.autoView('nucleic') +}) diff --git a/examples/examples/scripts/component/structure-multiModel.js b/examples/examples/scripts/component/structure-multiModel.js new file mode 100644 index 000000000..cc4386ab3 --- /dev/null +++ b/examples/examples/scripts/component/structure-multiModel.js @@ -0,0 +1,15 @@ + +stage.loadFile('data://1LVZ.pdb', { + firstModelOnly: true +}).then(function (o) { + o.addRepresentation('cartoon', { sele: '*' }) + stage.autoView() +}) + +stage.loadFile('data://md_1u19_trj.gro', { + asTrajectory: true +}).then(function (o) { + o.addRepresentation('cartoon', { sele: '*' }) + o.addTrajectory() + stage.autoView() +}) diff --git a/examples/examples/scripts/component/structure-superpose.js b/examples/examples/scripts/component/structure-superpose.js new file mode 100644 index 000000000..07dbffd9b --- /dev/null +++ b/examples/examples/scripts/component/structure-superpose.js @@ -0,0 +1,25 @@ + +var s = '1-320:A' + +Promise.all([ + + stage.loadFile('data://1u19.pdb', { + sele: ':A' + }).then(function (o) { + o.addRepresentation('cartoon', { sele: s }) + o.addRepresentation('ball+stick', { sele: s }) + return o + }), + + stage.loadFile('data://3dqb.pdb', { + sele: ':A' + }).then(function (o) { + o.addRepresentation('cartoon', { sele: s }) + o.addRepresentation('licorice', { sele: s }) + return o + }) + +]).then(function (ol) { + ol[ 0 ].superpose(ol[ 1 ], false, s) + ol[ 0 ].autoView(':A') +}) diff --git a/examples/examples/scripts/component/transform.js b/examples/examples/scripts/component/transform.js new file mode 100644 index 000000000..60d8e6fd5 --- /dev/null +++ b/examples/examples/scripts/component/transform.js @@ -0,0 +1,21 @@ + +Promise.all([ + + stage.loadFile('data://d1h4vb1.ent'), + stage.loadFile('data://d1nj1a1.ent') + +]).then(function (ol) { + ol[ 0 ].addRepresentation('cartoon', { color: 'skyblue' }) + ol[ 1 ].addRepresentation('cartoon', { color: 'tomato' }) + + var m = new NGL.Matrix4().fromArray([ + -0.4736676916, -0.0672340378, -0.8781335332, -47.8160381451, + -0.875018823, -0.077179501, 0.4778968341, -17.6453935901, + -0.0999048417, 0.9947476609, -0.0222736126, 78.0472326663, + 0, 0, 0, 1 + ]).transpose() + + ol[ 1 ].setTransform(m) + + stage.autoView() +}) diff --git a/examples/examples/scripts/interactive/annotation.js b/examples/examples/scripts/interactive/annotation.js new file mode 100644 index 000000000..8b943c62d --- /dev/null +++ b/examples/examples/scripts/interactive/annotation.js @@ -0,0 +1,31 @@ + +stage.loadFile('data://3SN6.cif').then(function (o) { + o.addRepresentation('cartoon', { color: 'chainname' }) + + var chainData = { + 'A': { text: 'alpha subunit', color: 'firebrick' }, + 'B': { text: 'beta subunit', color: 'orange' }, + 'G': { text: 'gamma subunit', color: 'khaki' }, + 'R': { text: 'beta 2 adrenergic receptor', color: 'skyblue' }, + 'N': { text: 'nanobody', color: 'royalblue' } + } + + var ap = o.structure.getAtomProxy() + o.structure.eachChain(function (cp) { + ap.index = cp.atomOffset + Math.floor(cp.atomCount / 2) + var elm = document.createElement('div') + elm.innerText = chainData[ cp.chainname ].text + elm.style.color = 'black' + elm.style.backgroundColor = chainData[ cp.chainname ].color + elm.style.padding = '8px' + o.addAnnotation(ap.positionToVector3(), elm) + }, new NGL.Selection('polymer')) + + o.autoView() + + var pa = o.structure.getPrincipalAxes() + var q = pa.getRotationQuaternion() + q.multiply(o.quaternion.clone().inverse()) + stage.animationControls.rotate(q, 0) + stage.animationControls.move(o.getCenter(), 0) +}) diff --git a/examples/examples/scripts/interactive/crosslinking.js b/examples/examples/scripts/interactive/crosslinking.js new file mode 100644 index 000000000..344ff5482 --- /dev/null +++ b/examples/examples/scripts/interactive/crosslinking.js @@ -0,0 +1,884 @@ +// Handle window resizing +window.addEventListener('resize', function () { + stage.handleResize() +}, false) + +var newDiv = document.getElementById('viewport').appendChild(document.createElement('div')) +newDiv.setAttribute('style', 'position: absolute; top: 0; left: 20px') +newDiv.innerHTML = '

Example Cross-Links over Human Serum Albumin

Data courtessy of Adam Belsom, Rappsilber Lab

Cross-Link Quality Filter

' + +// example crosslink data +var links = [{ + 'atoms': [3296, 3924], + 'data': { + 'score': 19 + } +}, { + 'atoms': [1497, 3368], + 'data': { + 'score': 17.34 + } +}, { + 'atoms': [955, 1278], + 'data': { + 'score': 17.32 + } +}, { + 'atoms': [1004, 1290], + 'data': { + 'score': 17.03 + } +}, { + 'atoms': [1029, 1290], + 'data': { + 'score': 16.94 + } +}, { + 'atoms': [2077, 2257], + 'data': { + 'score': 16.5 + } +}, { + 'atoms': [1641, 2767], + 'data': { + 'score': 15.92 + } +}, { + 'atoms': [3287, 3924], + 'data': { + 'score': 15.83 + } +}, { + 'atoms': [2687, 2850], + 'data': { + 'score': 15.73 + } +}, { + 'atoms': [949, 1290], + 'data': { + 'score': 15.7 + } +}, { + 'atoms': [1040, 1290], + 'data': { + 'score': 15.23 + } +}, { + 'atoms': [949, 1278], + 'data': { + 'score': 15.16 + } +}, { + 'atoms': [306, 541], + 'data': { + 'score': 14.69 + } +}, { + 'atoms': [1004, 1278], + 'data': { + 'score': 14.5 + } +}, { + 'atoms': [1013, 1290], + 'data': { + 'score': 14.37 + } +}, { + 'atoms': [3183, 4328], + 'data': { + 'score': 14.19 + } +}, { + 'atoms': [1884, 1900], + 'data': { + 'score': 13.99 + } +}, { + 'atoms': [812, 3684], + 'data': { + 'score': 13.94 + } +}, { + 'atoms': [1013, 1258], + 'data': { + 'score': 13.89 + } +}, { + 'atoms': [3384, 4113], + 'data': { + 'score': 13.78 + } +}, { + 'atoms': [3303, 3924], + 'data': { + 'score': 13.69 + } +}, { + 'atoms': [1497, 3377], + 'data': { + 'score': 13.42 + } +}, { + 'atoms': [329, 541], + 'data': { + 'score': 13.4 + } +}, { + 'atoms': [955, 1309], + 'data': { + 'score': 13.38 + } +}, { + 'atoms': [89, 1278], + 'data': { + 'score': 13.35 + } +}, { + 'atoms': [462, 479], + 'data': { + 'score': 13.17 + } +}, { + 'atoms': [399, 541], + 'data': { + 'score': 13.14 + } +}, { + 'atoms': [1493, 1511], + 'data': { + 'score': 13.11 + } +}, { + 'atoms': [1497, 3361], + 'data': { + 'score': 13.09 + } +}, { + 'atoms': [688, 742], + 'data': { + 'score': 13.08 + } +}, { + 'atoms': [321, 541], + 'data': { + 'score': 13.05 + } +}, { + 'atoms': [2850, 2983], + 'data': { + 'score': 13.02 + } +}, { + 'atoms': [1194, 1565], + 'data': { + 'score': 13 + } +}, { + 'atoms': [996, 1290], + 'data': { + 'score': 12.91 + } +}, { + 'atoms': [1497, 3571], + 'data': { + 'score': 12.76 + } +}, { + 'atoms': [98, 1258], + 'data': { + 'score': 12.74 + } +}, { + 'atoms': [77, 1290], + 'data': { + 'score': 12.72 + } +}, { + 'atoms': [263, 1057], + 'data': { + 'score': 12.69 + } +}, { + 'atoms': [955, 1231], + 'data': { + 'score': 12.68 + } +}, { + 'atoms': [955, 1290], + 'data': { + 'score': 12.66 + } +}, { + 'atoms': [1215, 1278], + 'data': { + 'score': 12.62 + } +}, { + 'atoms': [1668, 1831], + 'data': { + 'score': 12.56 + } +}, { + 'atoms': [69, 1258], + 'data': { + 'score': 12.47 + } +}, { + 'atoms': [3943, 4001], + 'data': { + 'score': 12.46 + } +}, { + 'atoms': [955, 1258], + 'data': { + 'score': 12.39 + } +}, { + 'atoms': [967, 1290], + 'data': { + 'score': 12.33 + } +}, { + 'atoms': [1493, 3346], + 'data': { + 'score': 12.32 + } +}, { + 'atoms': [2065, 2308], + 'data': { + 'score': 12.23 + } +}, { + 'atoms': [1632, 2767], + 'data': { + 'score': 12.2 + } +}, { + 'atoms': [1004, 1258], + 'data': { + 'score': 12.16 + } +}, { + 'atoms': [1565, 2362], + 'data': { + 'score': 12.15 + } +}, { + 'atoms': [77, 1258], + 'data': { + 'score': 12.09 + } +}, { + 'atoms': [1159, 1557], + 'data': { + 'score': 12.04 + } +}, { + 'atoms': [1652, 2767], + 'data': { + 'score': 12.03 + } +}, { + 'atoms': [4412, 4510], + 'data': { + 'score': 11.95 + } +}, { + 'atoms': [1242, 1565], + 'data': { + 'score': 11.95 + } +}, { + 'atoms': [3353, 3421], + 'data': { + 'score': 11.93 + } +}, { + 'atoms': [2861, 2983], + 'data': { + 'score': 11.87 + } +}, { + 'atoms': [3992, 4159], + 'data': { + 'score': 11.79 + } +}, { + 'atoms': [949, 1258], + 'data': { + 'score': 11.75 + } +}, { + 'atoms': [1517, 1546], + 'data': { + 'score': 11.74 + } +}, { + 'atoms': [2687, 2937], + 'data': { + 'score': 11.71 + } +}, { + 'atoms': [2065, 2350], + 'data': { + 'score': 11.6 + } +}, { + 'atoms': [4026, 4159], + 'data': { + 'score': 11.59 + } +}, { + 'atoms': [2065, 2301], + 'data': { + 'score': 11.59 + } +}, { + 'atoms': [3368, 3421], + 'data': { + 'score': 11.56 + } +}, { + 'atoms': [1668, 2767], + 'data': { + 'score': 11.53 + } +}, { + 'atoms': [988, 1290], + 'data': { + 'score': 11.52 + } +}, { + 'atoms': [3753, 3936], + 'data': { + 'score': 11.51 + } +}, { + 'atoms': [1223, 1565], + 'data': { + 'score': 11.46 + } +}, { + 'atoms': [69, 377], + 'data': { + 'score': 11.43 + } +}, { + 'atoms': [4340, 4433], + 'data': { + 'score': 11.39 + } +}, { + 'atoms': [3987, 4159], + 'data': { + 'score': 11.3 + } +}, { + 'atoms': [2679, 3508], + 'data': { + 'score': 11.29 + } +}, { + 'atoms': [2056, 3121], + 'data': { + 'score': 11.25 + } +}, { + 'atoms': [2523, 2767], + 'data': { + 'score': 11.21 + } +}, { + 'atoms': [3762, 4463], + 'data': { + 'score': 11.2 + } +}, { + 'atoms': [3287, 3908], + 'data': { + 'score': 11.15 + } +}, { + 'atoms': [49, 470], + 'data': { + 'score': 11.11 + } +}, { + 'atoms': [49, 1048], + 'data': { + 'score': 11.07 + } +}, { + 'atoms': [2051, 2065], + 'data': { + 'score': 11.04 + } +}, { + 'atoms': [2528, 2795], + 'data': { + 'score': 10.99 + } +}, { + 'atoms': [2065, 2239], + 'data': { + 'score': 10.96 + } +}, { + 'atoms': [2065, 2342], + 'data': { + 'score': 10.92 + } +}, { + 'atoms': [1608, 3604], + 'data': { + 'score': 10.91 + } +}, { + 'atoms': [49, 1258], + 'data': { + 'score': 10.9 + } +}, { + 'atoms': [1497, 1591], + 'data': { + 'score': 10.8 + } +}, { + 'atoms': [4519, 4541], + 'data': { + 'score': 10.77 + } +}, { + 'atoms': [1215, 1565], + 'data': { + 'score': 10.77 + } +}, { + 'atoms': [3441, 3456], + 'data': { + 'score': 10.72 + } +}, { + 'atoms': [4001, 4168], + 'data': { + 'score': 10.69 + } +}, { + 'atoms': [3924, 4256], + 'data': { + 'score': 10.55 + } +}, { + 'atoms': [1432, 1565], + 'data': { + 'score': 10.51 + } +}, { + 'atoms': [1608, 1657], + 'data': { + 'score': 10.45 + } +}, { + 'atoms': [688, 784], + 'data': { + 'score': 10.44 + } +}, { + 'atoms': [4159, 4328], + 'data': { + 'score': 10.41 + } +}, { + 'atoms': [3746, 3762], + 'data': { + 'score': 10.35 + } +}, { + 'atoms': [1457, 1497], + 'data': { + 'score': 10.34 + } +}, { + 'atoms': [955, 1375], + 'data': { + 'score': 10.33 + } +}, { + 'atoms': [3183, 3401], + 'data': { + 'score': 10.28 + } +}, { + 'atoms': [49, 1278], + 'data': { + 'score': 10.24 + } +}, { + 'atoms': [69, 1290], + 'data': { + 'score': 10.11 + } +}, { + 'atoms': [3441, 3477], + 'data': { + 'score': 10.09 + } +}, { + 'atoms': [1040, 1066], + 'data': { + 'score': 10.05 + } +}, { + 'atoms': [2767, 3762], + 'data': { + 'score': 10.05 + } +}, { + 'atoms': [1, 419], + 'data': { + 'score': 9.94 + } +}, { + 'atoms': [1565, 2301], + 'data': { + 'score': 9.88 + } +}, { + 'atoms': [2537, 2804], + 'data': { + 'score': 9.86 + } +}, { + 'atoms': [4328, 4541], + 'data': { + 'score': 9.83 + } +}, { + 'atoms': [1048, 1066], + 'data': { + 'score': 9.8 + } +}, { + 'atoms': [107, 1258], + 'data': { + 'score': 9.79 + } +}, { + 'atoms': [3278, 3900], + 'data': { + 'score': 9.75 + } +}, { + 'atoms': [60, 406], + 'data': { + 'score': 9.74 + } +}, { + 'atoms': [1617, 2767], + 'data': { + 'score': 9.71 + } +}, { + 'atoms': [3943, 4019], + 'data': { + 'score': 9.68 + } +}, { + 'atoms': [2835, 2972], + 'data': { + 'score': 9.63 + } +}, { + 'atoms': [49, 1290], + 'data': { + 'score': 9.57 + } +}, { + 'atoms': [4403, 4463], + 'data': { + 'score': 9.37 + } +}, { + 'atoms': [1448, 3571], + 'data': { + 'score': 9.33 + } +}, { + 'atoms': [2662, 3421], + 'data': { + 'score': 9.31 + } +}, { + 'atoms': [1, 49], + 'data': { + 'score': 9.29 + } +}, { + 'atoms': [3296, 3421], + 'data': { + 'score': 9.27 + } +}, { + 'atoms': [60, 949], + 'data': { + 'score': 9.17 + } +}, { + 'atoms': [1517, 1565], + 'data': { + 'score': 9.15 + } +}, { + 'atoms': [3421, 3477], + 'data': { + 'score': 9.11 + } +}, { + 'atoms': [4052, 4177], + 'data': { + 'score': 9.11 + } +}, { + 'atoms': [3113, 3468], + 'data': { + 'score': 9.11 + } +}, { + 'atoms': [503, 550], + 'data': { + 'score': 9.07 + } +}, { + 'atoms': [2528, 2818], + 'data': { + 'score': 9.06 + } +}, { + 'atoms': [1057, 1290], + 'data': { + 'score': 8.93 + } +}, { + 'atoms': [4256, 4277], + 'data': { + 'score': 8.9 + } +}, { + 'atoms': [2826, 2911], + 'data': { + 'score': 8.75 + } +}, { + 'atoms': [1497, 3384], + 'data': { + 'score': 8.67 + } +}, { + 'atoms': [3121, 3421], + 'data': { + 'score': 8.64 + } +}, { + 'atoms': [529, 564], + 'data': { + 'score': 8.5 + } +}, { + 'atoms': [60, 1299], + 'data': { + 'score': 8.49 + } +}, { + 'atoms': [3917, 4256], + 'data': { + 'score': 8.48 + } +}, { + 'atoms': [1493, 1517], + 'data': { + 'score': 8.39 + } +}, { + 'atoms': [1511, 1557], + 'data': { + 'score': 8.31 + } +}, { + 'atoms': [1506, 1565], + 'data': { + 'score': 8.3 + } +}, { + 'atoms': [1432, 3421], + 'data': { + 'score': 8.3 + } +}, { + 'atoms': [60, 399], + 'data': { + 'score': 8.29 + } +}, { + 'atoms': [3924, 4272], + 'data': { + 'score': 8.26 + } +}, { + 'atoms': [1497, 3430], + 'data': { + 'score': 8.24 + } +}, { + 'atoms': [2662, 3774], + 'data': { + 'score': 8.19 + } +}, { + 'atoms': [60, 1304], + 'data': { + 'score': 7.88 + } +}, { + 'atoms': [1497, 3707], + 'data': { + 'score': 7.6 + } +}, { + 'atoms': [3150, 3421], + 'data': { + 'score': 7.46 + } +}, { + 'atoms': [3332, 3421], + 'data': { + 'score': 7.41 + } +}, { + 'atoms': [2687, 3503], + 'data': { + 'score': 6.81 + } +}] + +var reps = {} // store ngl representations + +// make a map of the links accessible by atom indices for use in colour scheme stuff +var linkMap = {} +links.forEach(function (link) { + var atoms = link.atoms + linkMap[atoms[0] + '-' + atoms[1]] = link +}) + +// make a colour scheme that grabs the score of each link and uses it to return a colour +var initColourSchemes = function () { + var linkColourScheme = function () { + var colCache = {} + + this.bondColor = function (b) { + var origLink = linkMap[b.atomIndex1 + '-' + b.atomIndex2] + + if (origLink) { + var score = origLink.data.score + var col24bit = colCache[score] + if (col24bit === undefined) { + var i = score < valStops[1] ? 1 : 2 + var pct = (score - valStops[i - 1]) / (valStops[i] - valStops[i - 1]) + var col3 = {} + // aargh semi-colon needed at start of line + ;['r', 'g', 'b'].forEach(function (chan) { + col3[chan] = colStops[i - 1][chan] + (colStops[i][chan] - colStops[i - 1][chan]) * pct + }) + col24bit = col3 ? (col3.r << 16) + (col3.g << 8) + col3.b : 255 + colCache[score] = col24bit + } + return col24bit + } + return (128 << 16) + (128 << 8) + 128 // grey default + } + } + + reps.linkColourScheme = NGL.ColormakerRegistry.addScheme(linkColourScheme, 'xlink') +} +initColourSchemes() + +// return unique atom indices as a selection from a set of pairs of atom indices +var makeAtomSelection = function (someLinks) { + var atomSet = new Set() + someLinks.forEach(function (link) { + atomSet.add(link.atoms[0]) + atomSet.add(link.atoms[1]) + }) + var atomSelection = '@' + Array.from(atomSet).join(',') + return atomSelection +} + +// calculate extremes of score distribution for setting up initial slider and colour scale values +var min = Number.POSITIVE_INFINITY +var max = Number.NEGATIVE_INFINITY +links.forEach(function (link) { + var score = link.data.score + if (score !== undefined && score < min) { min = score } + if (score !== undefined && score > max) { max = score } +}) +document.getElementById('scoreSlider').min = min +document.getElementById('scoreSlider').max = max + 1 +document.getElementById('minValue').textContent = min +document.getElementById('maxValue').textContent = max + 1 + +var colStops = [{r: 0, g: 0, b: 128}, {r: 128, g: 255, b: 255}, {r: 255, g: 255, b: 0}] +var valStops = [min, (min + max) / 2, max] + +// listener for dragging slider, filter out links with score values smaller than slider value +document.getElementById('scoreSlider').addEventListener('input', function (evt) { + var val = +evt.target.value + var filteredLinks = links.filter(function (link) { + return link.data.score >= val + }) + reps.links.setParameters({ + atomPair: filteredLinks.map(function (fl) { + return fl.atoms + }) + }) + reps.residues.setSelection(makeAtomSelection(filteredLinks)) +}) + +// initial atom selection for residues +var startAtomSel = makeAtomSelection(links) + +// load pdb file and set up representations +stage.loadFile('rcsb://1AO6', { + sele: ':A' +}).then(function (o) { // restrict to 1 chain cos links are on the monomer + o.addRepresentation('cartoon', { + color: '#666' + }) + + var baseLinkScale = 3 + + reps.links = o.addRepresentation('distance', { + atomPair: links.map(function (l) { + return l.atoms + }), + // colorValue: 'yellow', + colorScheme: reps.linkColourScheme, + labelSize: 4, + labelColor: 'white', + labelVisible: true, + labelUnit: 'angstrom', + radiusScale: baseLinkScale, + opacity: 1, + name: 'link', + side: 'front', + useCylinder: true + }) + + reps.residues = o.addRepresentation('spacefill', { + sele: startAtomSel, + color: '#ccc', + // colorScale: ['#44f', '#444'], + radiusScale: 0.6, + name: 'res' + }) + + o.autoView(':A') // center on chain A +}) diff --git a/examples/examples/scripts/interactive/hover-tooltip.js b/examples/examples/scripts/interactive/hover-tooltip.js new file mode 100644 index 000000000..f98890d06 --- /dev/null +++ b/examples/examples/scripts/interactive/hover-tooltip.js @@ -0,0 +1,34 @@ + +// create tooltip element and add to document body +var tooltip = document.createElement('div') +Object.assign(tooltip.style, { + display: 'none', + position: 'fixed', + zIndex: 10, + pointerEvents: 'none', + backgroundColor: 'rgba( 0, 0, 0, 0.6 )', + color: 'lightgrey', + padding: '8px', + fontFamily: 'sans-serif' +}) +document.body.appendChild(tooltip) + +// load a structure file +stage.loadFile('data://1blu.mmtf', { defaultRepresentation: true }) + +// remove default hoverPick mouse action +stage.mouseControls.remove('hoverPick') + +// listen to `hovered` signal to move tooltip around and change its text +stage.signals.hovered.add(function (pickingProxy) { + if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) { + var atom = pickingProxy.atom || pickingProxy.closestBondAtom + var mp = pickingProxy.mouse.position + tooltip.innerText = 'ATOM: ' + atom.qualifiedName() + tooltip.style.bottom = window.innerHeight - mp.y + 3 + 'px' + tooltip.style.left = mp.x + 3 + 'px' + tooltip.style.display = 'block' + } else { + tooltip.style.display = 'none' + } +}) diff --git a/examples/examples/scripts/interactive/interpolate.js b/examples/examples/scripts/interactive/interpolate.js new file mode 100644 index 000000000..204506088 --- /dev/null +++ b/examples/examples/scripts/interactive/interpolate.js @@ -0,0 +1,20 @@ + +stage.loadFile('data://lig0FG.2models.pdb', { + asTrajectory: true +}).then(function (o) { + var traj = o.addTrajectory().trajectory + var player = new NGL.TrajectoryPlayer(traj, { + step: 1, + timeout: 70, + interpolateStep: 100, + start: 0, + end: traj.numframes, + interpolateType: 'linear', + mode: 'once', + direction: 'bounce' + }) + player.play() + + o.addRepresentation('licorice') + o.autoView() +}) diff --git a/examples/examples/scripts/interactive/ligand-viewer.js b/examples/examples/scripts/interactive/ligand-viewer.js new file mode 100644 index 000000000..2a67e0f92 --- /dev/null +++ b/examples/examples/scripts/interactive/ligand-viewer.js @@ -0,0 +1,627 @@ + +stage.setParameters({ + backgroundColor: 'white' +}) + +function addElement (el) { + Object.assign(el.style, { + position: 'absolute', + zIndex: 10 + }) + stage.viewer.container.appendChild(el) +} + +function createElement (name, properties, style) { + var el = document.createElement(name) + Object.assign(el, properties) + Object.assign(el.style, style) + return el +} + +function createSelect (options, properties, style) { + var select = createElement('select', properties, style) + options.forEach(function (d) { + select.add(createElement('option', { + value: d[ 0 ], text: d[ 1 ] + })) + }) + return select +} + +function createFileButton (label, properties, style) { + var input = createElement('input', Object.assign({ + type: 'file' + }, properties), { display: 'none' }) + addElement(input) + var button = createElement('input', { + value: label, + type: 'button', + onclick: function () { input.click() } + }, style) + return button +} + +var topPosition = 12 + +function getTopPosition (increment) { + if (increment) topPosition += increment + return topPosition + 'px' +} + +// create tooltip element and add to document body +var tooltip = document.createElement('div') +Object.assign(tooltip.style, { + display: 'none', + position: 'fixed', + zIndex: 10, + pointerEvents: 'none', + backgroundColor: 'rgba( 0, 0, 0, 0.6 )', + color: 'lightgrey', + padding: '8px', + fontFamily: 'sans-serif' +}) +document.body.appendChild(tooltip) + +// remove default hoverPick mouse action +stage.mouseControls.remove('hoverPick') + +// listen to `hovered` signal to move tooltip around and change its text +stage.signals.hovered.add(function (pickingProxy) { + if (pickingProxy) { + if (pickingProxy.atom || pickingProxy.bond) { + var atom = pickingProxy.atom || pickingProxy.closestBondAtom + var vm = atom.structure.data['@valenceModel'] + if (vm && vm.idealValence) { + tooltip.innerHTML = `${pickingProxy.getLabel()}
+
+ Atom: ${atom.qualifiedName()}
+ ideal valence: ${vm.idealValence[atom.index]}
+ ideal geometry: ${vm.idealGeometry[atom.index]}
+ implicit charge: ${vm.implicitCharge[atom.index]}
+ formal charge: ${atom.formalCharge === null ? '?' : atom.formalCharge}
+ aromatic: ${atom.aromatic ? 'true' : 'false'}
+ ` + } else if (vm && vm.charge) { + tooltip.innerHTML = `${pickingProxy.getLabel()}
+
+ Atom: ${atom.qualifiedName()}
+ vm charge: ${vm.charge[atom.index]}
+ vm implicitH: ${vm.implicitH[atom.index]}
+ vm totalH: ${vm.totalH[atom.index]}
+ vm geom: ${vm.idealGeometry[atom.index]}
+ formal charge: ${atom.formalCharge === null ? '?' : atom.formalCharge}
+ aromatic: ${atom.aromatic ? 'true' : 'false'}
+ ` + } else { + tooltip.innerHTML = `${pickingProxy.getLabel()}` + } + } else { + tooltip.innerHTML = `${pickingProxy.getLabel()}` + } + var mp = pickingProxy.mouse.position + tooltip.style.bottom = window.innerHeight - mp.y + 3 + 'px' + tooltip.style.left = mp.x + 3 + 'px' + tooltip.style.display = 'block' + } else { + tooltip.style.display = 'none' + } +}) + +stage.signals.clicked.add(function (pickingProxy) { + if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) { + console.log(pickingProxy.atom || pickingProxy.closestBondAtom) + } +}) + +var ligandSele = '( not polymer or not ( protein or nucleic ) ) and not ( water or ACE or NH2 )' + +var pocketRadius = 0 +var pocketRadiusClipFactor = 1 + +var cartoonRepr, backboneRepr, spacefillRepr, neighborRepr, ligandRepr, contactRepr, pocketRepr, labelRepr + +var struc +var neighborSele +var sidechainAttached = false + +function loadStructure (input) { + struc = undefined + stage.setFocus(0) + stage.removeAllComponents() + ligandSelect.innerHTML = '' + clipNearRange.value = 0 + clipRadiusRange.value = 100 + pocketOpacityRange.value = 0 + cartoonCheckbox.checked = false + backboneCheckbox.checked = false + hydrogenCheckbox.checked = true + hydrophobicCheckbox.checked = false + hydrogenBondCheckbox.checked = true + weakHydrogenBondCheckbox.checked = false + waterHydrogenBondCheckbox.checked = true + backboneHydrogenBondCheckbox.checked = true + halogenBondCheckbox.checked = true + metalInteractionCheckbox.checked = true + saltBridgeCheckbox.checked = true + cationPiCheckbox.checked = true + piStackingCheckbox.checked = true + return stage.loadFile(input).then(function (o) { + struc = o + setLigandOptions() + setChainOptions() + setResidueOptions() + o.autoView() + cartoonRepr = o.addRepresentation('cartoon', { + visible: false + }) + backboneRepr = o.addRepresentation('backbone', { + visible: true, + colorValue: 'lightgrey', + radiusScale: 2 + }) + spacefillRepr = o.addRepresentation('spacefill', { + sele: ligandSele, + visible: true + }) + neighborRepr = o.addRepresentation('ball+stick', { + sele: 'none', + aspectRatio: 1.1, + colorValue: 'lightgrey', + multipleBond: 'symmetric' + }) + ligandRepr = o.addRepresentation('ball+stick', { + multipleBond: 'symmetric', + colorValue: 'grey', + sele: 'none', + aspectRatio: 1.2, + radiusScale: 2.5 + }) + contactRepr = o.addRepresentation('contact', { + sele: 'none', + radiusSize: 0.07, + weakHydrogenBond: false, + waterHydrogenBond: false, + backboneHydrogenBond: true + }) + pocketRepr = o.addRepresentation('surface', { + sele: 'none', + lazy: true, + visibility: true, + clipNear: 0, + opaqueBack: false, + opacity: 0.0, + color: 'hydrophobicity', + roughness: 1.0, + surfaceType: 'av' + }) + labelRepr = o.addRepresentation('label', { + sele: 'none', + color: '#333333', + yOffset: 0.2, + zOffset: 2.0, + attachment: 'bottom-center', + showBorder: true, + borderColor: 'lightgrey', + borderWidth: 0.25, + disablePicking: true, + radiusType: 'size', + radiusSize: 0.8, + labelType: 'residue', + labelGrouping: 'residue' + }) + }) +} + +function setLigandOptions () { + ligandSelect.innerHTML = '' + var options = [['', 'select ligand']] + struc.structure.eachResidue(function (rp) { + if (rp.isWater()) return + var sele = '' + if (rp.resno !== undefined) sele += rp.resno + if (rp.inscode) sele += '^' + rp.inscode + if (rp.chain) sele += ':' + rp.chainname + var name = (rp.resname ? '[' + rp.resname + ']' : '') + sele + if (rp.entity && rp.entity.description) name += ' (' + rp.entity.description + ')' + options.push([sele, name]) + }, new NGL.Selection(ligandSele)) + options.forEach(function (d) { + ligandSelect.add(createElement('option', { + value: d[0], text: d[1] + })) + }) +} + +function setChainOptions () { + chainSelect.innerHTML = '' + var options = [['', 'select chain']] + struc.structure.eachChain(function (cp) { + var name = cp.chainname + if (cp.entity && cp.entity.description) name += ' (' + cp.entity.description + ')' + options.push([cp.chainname, name]) + }, new NGL.Selection('polymer')) + options.forEach(function (d) { + chainSelect.add(createElement('option', { + value: d[0], text: d[1] + })) + }) +} + +function setResidueOptions (chain) { + residueSelect.innerHTML = '' + var options = [['', 'select residue']] + if (chain) { + struc.structure.eachResidue(function (rp) { + var sele = '' + if (rp.resno !== undefined) sele += rp.resno + if (rp.inscode) sele += '^' + rp.inscode + if (rp.chain) sele += ':' + rp.chainname + var name = (rp.resname ? '[' + rp.resname + ']' : '') + sele + options.push([sele, name]) + }, new NGL.Selection('polymer and :' + chain)) + } + options.forEach(function (d) { + residueSelect.add(createElement('option', { + value: d[0], text: d[1] + })) + }) +} + +var loadStructureButton = createFileButton('load structure', { + accept: '.pdb,.cif,.ent,.gz,.mol2', + onchange: function (e) { + if (e.target.files[ 0 ]) { + loadStructure(e.target.files[ 0 ]) + } + } +}, { top: getTopPosition(), left: '12px' }) +addElement(loadStructureButton) + +var loadPdbidText = createElement('span', { + innerText: 'load pdb id' +}, { top: getTopPosition(20), left: '12px', color: 'grey' }) +addElement(loadPdbidText) + +var loadPdbidInput = createElement('input', { + type: 'text', + title: 'press enter to load pdbid', + onkeypress: function (e) { + if (e.keyCode === 13) { + e.preventDefault() + loadStructure('rcsb://' + e.target.value) + } + } +}, { top: getTopPosition(20), left: '12px', width: '120px' }) +addElement(loadPdbidInput) + +function showFull () { + ligandSelect.value = '' + + backboneRepr.setParameters({ radiusScale: 2 }) + backboneRepr.setVisibility(true) + spacefillRepr.setVisibility(true) + + ligandRepr.setVisibility(false) + neighborRepr.setVisibility(false) + contactRepr.setVisibility(false) + pocketRepr.setVisibility(false) + labelRepr.setVisibility(false) + + struc.autoView(2000) +} + +var fullButton = createElement('input', { + value: 'full structure', + type: 'button', + onclick: showFull +}, { top: getTopPosition(30), left: '12px' }) +addElement(fullButton) + +function showLigand (sele) { + var s = struc.structure + + var withinSele = s.getAtomSetWithinSelection(new NGL.Selection(sele), 5) + var withinGroup = s.getAtomSetWithinGroup(withinSele) + var expandedSele = withinGroup.toSeleString() + // neighborSele = '(' + expandedSele + ') and not (' + sele + ')' + neighborSele = expandedSele + + var sview = s.getView(new NGL.Selection(sele)) + pocketRadius = Math.max(sview.boundingBox.getSize(new NGL.Vector3()).length() / 2, 2) + 5 + var withinSele2 = s.getAtomSetWithinSelection(new NGL.Selection(sele), pocketRadius + 2) + var neighborSele2 = '(' + withinSele2.toSeleString() + ') and not (' + sele + ') and polymer' + + backboneRepr.setParameters({ radiusScale: 0.2 }) + backboneRepr.setVisibility(backboneCheckbox.checked) + spacefillRepr.setVisibility(false) + + ligandRepr.setVisibility(true) + neighborRepr.setVisibility(true) + contactRepr.setVisibility(true) + pocketRepr.setVisibility(true) + labelRepr.setVisibility(labelCheckbox.checked) + + ligandRepr.setSelection(sele) + neighborRepr.setSelection( + sidechainAttached ? '(' + neighborSele + ') and (sidechainAttached or not polymer)' : neighborSele + ) + contactRepr.setSelection(expandedSele) + pocketRepr.setSelection(neighborSele2) + pocketRepr.setParameters({ + clipRadius: pocketRadius * pocketRadiusClipFactor, + clipCenter: sview.center + }) + labelRepr.setSelection('(' + neighborSele + ') and not (water or ion)') + + struc.autoView(expandedSele, 2000) +} + +var ligandSelect = createSelect([], { + onchange: function (e) { + residueSelect.value = '' + var sele = e.target.value + if (!sele) { + showFull() + } else { + showLigand(sele) + } + } +}, { top: getTopPosition(30), left: '12px', width: '130px' }) +addElement(ligandSelect) + +var chainSelect = createSelect([], { + onchange: function (e) { + ligandSelect.value = '' + residueSelect.value = '' + setResidueOptions(e.target.value) + } +}, { top: getTopPosition(20), left: '12px', width: '130px' }) +addElement(chainSelect) + +var residueSelect = createSelect([], { + onchange: function (e) { + ligandSelect.value = '' + var sele = e.target.value + if (!sele) { + showFull() + } else { + showLigand(sele) + } + } +}, { top: getTopPosition(20), left: '12px', width: '130px' }) +addElement(residueSelect) + +addElement(createElement('span', { + innerText: 'pocket near clipping' +}, { top: getTopPosition(30), left: '12px', color: 'grey' })) +var clipNearRange = createElement('input', { + type: 'range', value: 0, min: 0, max: 10000, step: 1 +}, { top: getTopPosition(16), left: '12px' }) +clipNearRange.oninput = function (e) { + var sceneRadius = stage.viewer.boundingBox.getSize(new NGL.Vector3()).length() / 2 + + var f = pocketRadius / sceneRadius + var v = parseFloat(e.target.value) / 10000 // must be between 0 and 1 + var c = 0.5 - f / 2 + v * f + + pocketRepr.setParameters({ + clipNear: c * 100 // must be between 0 and 100 + }) +} +addElement(clipNearRange) + +addElement(createElement('span', { + innerText: 'pocket radius clipping' +}, { top: getTopPosition(20), left: '12px', color: 'grey' })) +var clipRadiusRange = createElement('input', { + type: 'range', value: 100, min: 1, max: 100, step: 1 +}, { top: getTopPosition(16), left: '12px' }) +clipRadiusRange.oninput = function (e) { + pocketRadiusClipFactor = parseFloat(e.target.value) / 100 + pocketRepr.setParameters({ clipRadius: pocketRadius * pocketRadiusClipFactor }) +} +addElement(clipRadiusRange) + +addElement(createElement('span', { + innerText: 'pocket opacity' +}, { top: getTopPosition(20), left: '12px', color: 'grey' })) +var pocketOpacityRange = createElement('input', { + type: 'range', value: 90, min: 0, max: 100, step: 1 +}, { top: getTopPosition(16), left: '12px' }) +pocketOpacityRange.oninput = function (e) { + pocketRepr.setParameters({ + opacity: parseFloat(e.target.value) / 100 + }) +} +addElement(pocketOpacityRange) + +var cartoonCheckbox = createElement('input', { + type: 'checkbox', + checked: false, + onchange: function (e) { + cartoonRepr.setVisibility(e.target.checked) + } +}, { top: getTopPosition(30), left: '12px' }) +addElement(cartoonCheckbox) +addElement(createElement('span', { + innerText: 'cartoon' +}, { top: getTopPosition(), left: '32px', color: 'grey' })) + +var backboneCheckbox = createElement('input', { + type: 'checkbox', + checked: false, + onchange: function (e) { + backboneRepr.setVisibility(e.target.checked) + } +}, { top: getTopPosition(20), left: '12px' }) +addElement(backboneCheckbox) +addElement(createElement('span', { + innerText: 'backbone' +}, { top: getTopPosition(), left: '32px', color: 'grey' })) + +var hydrogenCheckbox = createElement('input', { + type: 'checkbox', + checked: true, + onchange: function (e) { + if (e.target.checked) { + struc.setSelection('*') + } else { + struc.setSelection('not _H') + } + } +}, { top: getTopPosition(20), left: '12px' }) +addElement(hydrogenCheckbox) +addElement(createElement('span', { + innerText: 'hydrogen' +}, { top: getTopPosition(), left: '32px', color: 'grey' })) + +var sidechainAttachedCheckbox = createElement('input', { + type: 'checkbox', + checked: false, + onchange: function (e) { + sidechainAttached = e.target.checked + neighborRepr.setSelection( + sidechainAttached ? '(' + neighborSele + ') and (sidechainAttached or not polymer)' : neighborSele + ) + } +}, { top: getTopPosition(20), left: '12px' }) +addElement(sidechainAttachedCheckbox) +addElement(createElement('span', { + innerText: 'sidechainAttached' +}, { top: getTopPosition(), left: '32px', color: 'grey' })) + +var labelCheckbox = createElement('input', { + type: 'checkbox', + checked: true, + onchange: function (e) { + labelRepr.setVisibility(e.target.checked) + } +}, { top: getTopPosition(20), left: '12px' }) +addElement(labelCheckbox) +addElement(createElement('span', { + innerText: 'label' +}, { top: getTopPosition(), left: '32px', color: 'grey' })) + +var hydrophobicCheckbox = createElement('input', { + type: 'checkbox', + checked: false, + onchange: function (e) { + contactRepr.setParameters({ hydrophobic: e.target.checked }) + } +}, { top: getTopPosition(30), left: '12px' }) +addElement(hydrophobicCheckbox) +addElement(createElement('span', { + innerText: 'hydrophobic' +}, { top: getTopPosition(), left: '32px', color: 'grey' })) + +var hydrogenBondCheckbox = createElement('input', { + type: 'checkbox', + checked: false, + onchange: function (e) { + contactRepr.setParameters({ hydrogenBond: e.target.checked }) + } +}, { top: getTopPosition(20), left: '12px' }) +addElement(hydrogenBondCheckbox) +addElement(createElement('span', { + innerText: 'hbond' +}, { top: getTopPosition(), left: '32px', color: 'grey' })) + +var weakHydrogenBondCheckbox = createElement('input', { + type: 'checkbox', + checked: false, + onchange: function (e) { + contactRepr.setParameters({ weakHydrogenBond: e.target.checked }) + } +}, { top: getTopPosition(20), left: '12px' }) +addElement(weakHydrogenBondCheckbox) +addElement(createElement('span', { + innerText: 'weak hbond' +}, { top: getTopPosition(), left: '32px', color: 'grey' })) + +var waterHydrogenBondCheckbox = createElement('input', { + type: 'checkbox', + checked: false, + onchange: function (e) { + contactRepr.setParameters({ waterHydrogenBond: e.target.checked }) + } +}, { top: getTopPosition(20), left: '12px' }) +addElement(waterHydrogenBondCheckbox) +addElement(createElement('span', { + innerText: 'water-water hbond' +}, { top: getTopPosition(), left: '32px', color: 'grey' })) + +var backboneHydrogenBondCheckbox = createElement('input', { + type: 'checkbox', + checked: false, + onchange: function (e) { + contactRepr.setParameters({ backboneHydrogenBond: e.target.checked }) + } +}, { top: getTopPosition(20), left: '12px' }) +addElement(backboneHydrogenBondCheckbox) +addElement(createElement('span', { + innerText: 'backbone-backbone hbond' +}, { top: getTopPosition(), left: '32px', color: 'grey' })) + +var halogenBondCheckbox = createElement('input', { + type: 'checkbox', + checked: true, + onchange: function (e) { + contactRepr.setParameters({ halogenBond: e.target.checked }) + } +}, { top: getTopPosition(20), left: '12px' }) +addElement(halogenBondCheckbox) +addElement(createElement('span', { + innerText: 'halogen bond' +}, { top: getTopPosition(), left: '32px', color: 'grey' })) + +var metalInteractionCheckbox = createElement('input', { + type: 'checkbox', + checked: true, + onchange: function (e) { + contactRepr.setParameters({ metalComplex: e.target.checked }) + } +}, { top: getTopPosition(20), left: '12px' }) +addElement(metalInteractionCheckbox) +addElement(createElement('span', { + innerText: 'metal interaction' +}, { top: getTopPosition(), left: '32px', color: 'grey' })) + +var saltBridgeCheckbox = createElement('input', { + type: 'checkbox', + checked: true, + onchange: function (e) { + contactRepr.setParameters({ saltBridge: e.target.checked }) + } +}, { top: getTopPosition(20), left: '12px' }) +addElement(saltBridgeCheckbox) +addElement(createElement('span', { + innerText: 'salt bridge' +}, { top: getTopPosition(), left: '32px', color: 'grey' })) + +var cationPiCheckbox = createElement('input', { + type: 'checkbox', + checked: true, + onchange: function (e) { + contactRepr.setParameters({ cationPi: e.target.checked }) + } +}, { top: getTopPosition(20), left: '12px' }) +addElement(cationPiCheckbox) +addElement(createElement('span', { + innerText: 'cation-pi' +}, { top: getTopPosition(), left: '32px', color: 'grey' })) + +var piStackingCheckbox = createElement('input', { + type: 'checkbox', + checked: true, + onchange: function (e) { + contactRepr.setParameters({ piStacking: e.target.checked }) + } +}, { top: getTopPosition(20), left: '12px' }) +addElement(piStackingCheckbox) +addElement(createElement('span', { + innerText: 'pi-stacking' +}, { top: getTopPosition(), left: '32px', color: 'grey' })) + +loadStructure('rcsb://4cup').then(function () { + showLigand('ZYB') +}) diff --git a/examples/examples/scripts/interactive/simple-viewer.js b/examples/examples/scripts/interactive/simple-viewer.js new file mode 100644 index 000000000..87cbeb294 --- /dev/null +++ b/examples/examples/scripts/interactive/simple-viewer.js @@ -0,0 +1,125 @@ + +function addElement (el) { + Object.assign(el.style, { + position: 'absolute', + zIndex: 10 + }) + stage.viewer.container.appendChild(el) +} + +function createElement (name, properties, style) { + var el = document.createElement(name) + Object.assign(el, properties) + Object.assign(el.style, style) + return el +} + +function createSelect (options, properties, style) { + var select = createElement('select', properties, style) + options.forEach(function (d) { + select.add(createElement('option', { + value: d[ 0 ], text: d[ 1 ] + })) + }) + return select +} + +function createFileButton (label, properties, style) { + var input = createElement('input', Object.assign({ + type: 'file' + }, properties), { display: 'none' }) + addElement(input) + var button = createElement('input', { + value: label, + type: 'button', + onclick: function () { input.click() } + }, style) + return button +} + +function loadStructure (input) { + stage.removeAllComponents() + return stage.loadFile(input).then(function (o) { + o.autoView() + o.addRepresentation(polymerSelect.value, { + sele: 'polymer', + name: 'polymer' + }) + o.addRepresentation('ball+stick', { + name: 'ligand', + visible: ligandCheckbox.checked, + sele: 'not ( polymer or water or ion )' + }) + o.addRepresentation('spacefill', { + name: 'waterIon', + visible: waterIonCheckbox.checked, + sele: 'water or ion', + scale: 0.25 + }) + }) +} + +var loadStructureButton = createFileButton('load structure', { + accept: '.pdb,.cif,.ent,.gz', + onchange: function (e) { + if (e.target.files[ 0 ]) { + loadStructure(e.target.files[ 0 ]) + } + } +}, { top: '12px', left: '12px' }) +addElement(loadStructureButton) + +var polymerSelect = createSelect([ + [ 'cartoon', 'cartoon' ], + [ 'spacefill', 'spacefill' ], + [ 'licorice', 'licorice' ], + [ 'surface', 'surface' ] +], { + onchange: function (e) { + stage.getRepresentationsByName('polymer').dispose() + stage.eachComponent(function (o) { + o.addRepresentation(e.target.value, { + sele: 'polymer', + name: 'polymer' + }) + }) + } +}, { top: '36px', left: '12px' }) +addElement(polymerSelect) + +var ligandCheckbox = createElement('input', { + type: 'checkbox', + checked: true, + onchange: function (e) { + stage.getRepresentationsByName('ligand') + .setVisibility(e.target.checked) + } +}, { top: '60px', left: '12px' }) +addElement(ligandCheckbox) +addElement(createElement('span', { + innerText: 'ligand' +}, { top: '60px', left: '32px' })) + +var waterIonCheckbox = createElement('input', { + type: 'checkbox', + checked: false, + onchange: function (e) { + stage.getRepresentationsByName('waterIon') + .setVisibility(e.target.checked) + } +}, { top: '84px', left: '12px' }) +addElement(waterIonCheckbox) +addElement(createElement('span', { + innerText: 'water+ion' +}, { top: '84px', left: '32px' })) + +var centerButton = createElement('input', { + type: 'button', + value: 'center', + onclick: function () { + stage.autoView(1000) + } +}, { top: '108px', left: '12px' }) +addElement(centerButton) + +loadStructure('data://3SN6.cif') diff --git a/examples/examples/scripts/interactive/xray-viewer.js b/examples/examples/scripts/interactive/xray-viewer.js new file mode 100644 index 000000000..7856dd950 --- /dev/null +++ b/examples/examples/scripts/interactive/xray-viewer.js @@ -0,0 +1,455 @@ + +var edmapUrl = 'https://edmaps.rcsb.org/maps/' + +stage.setParameters({ + cameraType: 'orthographic', + mousePreset: 'coot' +}) + +function addElement (el) { + Object.assign(el.style, { + position: 'absolute', + zIndex: 10 + }) + stage.viewer.container.appendChild(el) +} + +function createElement (name, properties, style) { + var el = document.createElement(name) + Object.assign(el, properties) + Object.assign(el.style, style) + return el +} + +function createSelect (options, properties, style) { + var select = createElement('select', properties, style) + options.forEach(function (d) { + select.add(createElement('option', { + value: d[ 0 ], text: d[ 1 ] + })) + }) + return select +} + +function createFileButton (label, properties, style) { + var input = createElement('input', Object.assign({ + type: 'file' + }, properties), { display: 'none' }) + addElement(input) + var button = createElement('input', { + value: label, + type: 'button', + onclick: function () { input.click() } + }, style) + return button +} + +var scroll2fofc, scrollFofc + +function isolevelScroll (stage, delta) { + var d = Math.sign(delta) / 10 + stage.eachRepresentation(function (reprElem, comp) { + var p + if (scroll2fofc && reprElem === surf2fofc) { + p = reprElem.getParameters() + reprElem.setParameters({ isolevel: Math.max(0.01, p.isolevel + d) }) + } else if (scrollFofc && (reprElem === surfFofc || reprElem === surfFofcNeg)) { + p = reprElem.getParameters() + reprElem.setParameters({ isolevel: Math.max(0.01, p.isolevel + d) }) + } + }) +} + +stage.mouseControls.add('scroll', isolevelScroll) + +var struc +function loadStructure (input) { + struc = undefined + surf2fofc = undefined + surfFofc = undefined + surfFofcNeg = undefined + file2fofcText.innerText = '2fofc file: none' + fileFofcText.innerText = 'fofc file: none' + isolevel2fofcText.innerText = '' + isolevelFofcText.innerText = '' + boxSizeRange.value = 10 + seleInput.value = '' + stage.setFocus(0) + stage.removeAllComponents() + return stage.loadFile(input).then(function (o) { + fileStructureText.innerText = 'structure file: ' + o.name + struc = o + o.autoView() + o.addRepresentation('line', { + colorValue: 'yellow', + multipleBond: 'offset', + bondSpacing: 1.1, + linewidth: 6 + }) + o.addRepresentation('point', { + colorValue: 'yellow', + sizeAttenuation: false, + pointSize: 6, + alphaTest: 1, + useTexture: true + }) + }) +} + +var surf2fofc +function load2fofc (input) { + return stage.loadFile(input).then(function (o) { + file2fofcText.innerText = '2fofc file: ' + o.name + isolevel2fofcText.innerText = '2fofc level: 1.5\u03C3' + boxSizeRange.value = 10 + scrollSelect.value = '2fofc' + scroll2fofc = true + if (surfFofc) { + isolevelFofcText.innerText = 'fofc level: 3.0\u03C3' + surfFofc.setParameters({ isolevel: 3, boxSize: 10, contour: true, isolevelScroll: false }) + surfFofcNeg.setParameters({ isolevel: 3, boxSize: 10, contour: true, isolevelScroll: false }) + } + surf2fofc = o.addRepresentation('surface', { + color: 'skyblue', + isolevel: 1.5, + boxSize: 10, + useWorker: false, + contour: true, + opaqueBack: false, + isolevelScroll: false + }) + }) +} + +var surfFofc, surfFofcNeg +function loadFofc (input) { + return stage.loadFile(input).then(function (o) { + fileFofcText.innerText = 'fofc file: ' + o.name + isolevelFofcText.innerText = 'fofc level: 3.0\u03C3' + boxSizeRange.value = 10 + scrollSelect.value = '2fofc' + scrollFofc = false + if (surf2fofc) { + isolevel2fofcText.innerText = '2fofc level: 1.5\u03C3' + surf2fofc.setParameters({ isolevel: 1.5, boxSize: 10, contour: true, isolevelScroll: false }) + } + surfFofc = o.addRepresentation('surface', { + color: 'mediumseagreen', + isolevel: 3, + boxSize: 10, + useWorker: false, + contour: true, + opaqueBack: false, + isolevelScroll: false + }) + surfFofcNeg = o.addRepresentation('surface', { + color: 'tomato', + isolevel: 3, + negateIsolevel: true, + boxSize: 10, + useWorker: false, + contour: true, + opaqueBack: false, + isolevelScroll: false + }) + }) +} + +var loadStructureButton = createFileButton('load structure', { + accept: '.pdb,.cif,.ent,.gz', + onchange: function (e) { + if (e.target.files[ 0 ]) { + exampleSelect.value = '' + loadStructure(e.target.files[ 0 ]) + } + } +}, { top: '12px', left: '12px' }) +addElement(loadStructureButton) + +var load2fofcButton = createFileButton('load 2fofc', { + accept: '.map,.ccp4,.brix,.dsn6,.mrc,.gz', + onchange: function (e) { + if (e.target.files[ 0 ]) { + load2fofc(e.target.files[ 0 ]) + } + } +}, { top: '36px', left: '12px' }) +addElement(load2fofcButton) + +var loadFofcButton = createFileButton('load fofc', { + accept: '.map,.ccp4,.brix,.dsn6,.mrc,.gz', + onchange: function (e) { + if (e.target.files[ 0 ]) { + loadFofc(e.target.files[ 0 ]) + } + } +}, { top: '60px', left: '12px' }) +addElement(loadFofcButton) + +var exampleSelect = createSelect([ + [ '', 'load example' ], + [ '3ek3', '3ek3' ], + [ '3nzd', '3nzd' ], + [ '1lee', '1lee' ] +], { + onchange: function (e) { + var id = e.target.value + loadExample(id).then(function () { + if (id === '3nzd') { + seleInput.value = 'NDP' + } else if (id === '1lee') { + seleInput.value = 'R36 and (.C28 or .N1)' + } + applySele(seleInput.value) + }) + } +}, { top: '84px', left: '12px' }) +addElement(exampleSelect) + +var seleText = createElement('span', { + innerText: 'center selection', + title: 'press enter to apply and center' +}, { top: '114px', left: '12px', color: 'lightgrey' }) +addElement(seleText) + +var lastSele +function checkSele (str) { + var selection = new NGL.Selection(str) + return !selection.selection[ 'error' ] +} +function applySele (value) { + if (value) { + lastSele = value + struc.autoView(value) + var z = stage.viewer.camera.position.z + stage.setFocus(100 - Math.abs(z / 10)) + } +} +var seleInput = createElement('input', { + type: 'text', + title: 'press enter to apply and center', + onkeypress: function (e) { + var value = e.target.value + var character = String.fromCharCode(e.which) + if (e.keyCode === 13) { + e.preventDefault() + if (checkSele(value)) { + if (struc) { + applySele(value) + } + e.target.style.backgroundColor = 'white' + } else { + e.target.style.backgroundColor = 'tomato' + } + } else if (lastSele !== value + character) { + e.target.style.backgroundColor = 'skyblue' + } else { + e.target.style.backgroundColor = 'white' + } + } +}, { top: '134px', left: '12px', width: '120px' }) +addElement(seleInput) + +var surfaceSelect = createSelect([ + [ 'contour', 'contour' ], + [ 'wireframe', 'wireframe' ], + [ 'smooth', 'smooth' ], + [ 'flat', 'flat' ] +], { + onchange: function (e) { + var v = e.target.value + var p + if (v === 'contour') { + p = { + contour: true, + flatShaded: false, + opacity: 1, + metalness: 0, + wireframe: false + } + } else if (v === 'wireframe') { + p = { + contour: false, + flatShaded: false, + opacity: 1, + metalness: 0, + wireframe: true + } + } else if (v === 'smooth') { + p = { + contour: false, + flatShaded: false, + opacity: 0.5, + metalness: 0, + wireframe: false + } + } else if (v === 'flat') { + p = { + contour: false, + flatShaded: true, + opacity: 0.5, + metalness: 0.2, + wireframe: false + } + } + stage.getRepresentationsByName('surface').setParameters(p) + } +}, { top: '170px', left: '12px' }) +addElement(surfaceSelect) + +var toggle2fofcButton = createElement('input', { + type: 'button', + value: 'toggle 2fofc', + onclick: function (e) { + surf2fofc.toggleVisibility() + } +}, { top: '194px', left: '12px' }) +addElement(toggle2fofcButton) + +var toggleFofcButton = createElement('input', { + type: 'button', + value: 'toggle fofc', + onclick: function (e) { + surfFofc.toggleVisibility() + surfFofcNeg.toggleVisibility() + } +}, { top: '218px', left: '12px' }) +addElement(toggleFofcButton) + +addElement(createElement('span', { + innerText: 'box size' +}, { top: '242px', left: '12px', color: 'lightgrey' })) +var boxSizeRange = createElement('input', { + type: 'range', + value: 10, + min: 1, + max: 50, + step: 1, + oninput: function (e) { + stage.getRepresentationsByName('surface').setParameters({ + boxSize: parseInt(e.target.value) + }) + } +}, { top: '258px', left: '12px' }) +addElement(boxSizeRange) + +var screenshotButton = createElement('input', { + type: 'button', + value: 'screenshot', + onclick: function () { + stage.makeImage({ + factor: 1, + antialias: false, + trim: false, + transparent: false + }).then(function (blob) { + NGL.download(blob, 'ngl-xray-viewer-screenshot.png') + }) + } +}, { top: '282px', left: '12px' }) +addElement(screenshotButton) + +var scrollSelect = createSelect([ + [ '2fofc', 'scroll 2fofc' ], + [ 'fofc', 'scroll fofc' ], + [ 'both', 'scroll both' ] +], { + onchange: function (e) { + var v = e.target.value + if (v === '2fofc') { + scroll2fofc = true + scrollFofc = false + } else if (v === 'fofc') { + scroll2fofc = false + scrollFofc = true + } else if (v === 'both') { + scroll2fofc = true + scrollFofc = true + } + } +}, { top: '306px', left: '12px' }) +addElement(scrollSelect) + +var loadEdmapText = createElement('span', { + innerText: 'load edmap for pdb id', + title: 'press enter to load' +}, { top: '330px', left: '12px', color: 'lightgrey' }) +addElement(loadEdmapText) + +var loadEdmapInput = createElement('input', { + type: 'text', + title: 'press enter to load', + onkeypress: function (e) { + var value = e.target.value + if (e.keyCode === 13) { + e.preventDefault() + loadStructure('rcsb://' + value) + load2fofc(edmapUrl + value + '_2fofc.dsn6') + loadFofc(edmapUrl + value + '_fofc.dsn6') + } + } +}, { top: '350px', left: '12px', width: '120px' }) +addElement(loadEdmapInput) + +var isolevel2fofcText = createElement( + 'span', {}, { bottom: '32px', left: '12px', color: 'lightgrey' } +) +addElement(isolevel2fofcText) + +var isolevelFofcText = createElement( + 'span', {}, { bottom: '12px', left: '12px', color: 'lightgrey' } +) +addElement(isolevelFofcText) + +var fileStructureText = createElement('span', { + innerText: 'structure file: none' +}, { bottom: '52px', right: '12px', color: 'lightgrey' }) +addElement(fileStructureText) + +var file2fofcText = createElement('span', { + innerText: '2fofc file: none' +}, { bottom: '32px', right: '12px', color: 'lightgrey' }) +addElement(file2fofcText) + +var fileFofcText = createElement('span', { + innerText: 'fofc file: none' +}, { bottom: '12px', right: '12px', color: 'lightgrey' }) +addElement(fileFofcText) + +stage.mouseControls.add('scroll', function () { + if (surf2fofc) { + var level2fofc = surf2fofc.getParameters().isolevel.toFixed(1) + isolevel2fofcText.innerText = '2fofc level: ' + level2fofc + '\u03C3' + } + if (surfFofc) { + var levelFofc = surfFofc.getParameters().isolevel.toFixed(1) + isolevelFofcText.innerText = 'fofc level: ' + levelFofc + '\u03C3' + } +}) + +function loadExample (id) { + var pl + if (id === '3ek3') { + pl = [ + loadStructure('data://3ek3.cif'), + load2fofc('data://3ek3-2fofc.map.gz'), + loadFofc('data://3ek3-fofc.map.gz') + ] + } else if (id === '3nzd') { + pl = [ + loadStructure('data://3nzd.cif'), + load2fofc('data://3nzd.ccp4.gz'), + loadFofc('data://3nzd_diff.ccp4.gz') + ] + } else if (id === '1lee') { + pl = [ + loadStructure('data://1lee.pdb'), + load2fofc('data://1lee.ccp4'), + loadFofc('data://1lee_diff.ccp4') + ] + } + exampleSelect.value = '' + return Promise.all(pl) +} + +loadExample('3ek3') diff --git a/examples/examples/scripts/parser/brix.js b/examples/examples/scripts/parser/brix.js new file mode 100644 index 000000000..454f54240 --- /dev/null +++ b/examples/examples/scripts/parser/brix.js @@ -0,0 +1,10 @@ + +stage.loadFile('data://3str-2fofc.brix').then(function (o) { + o.addRepresentation('surface') + stage.autoView() +}) + +stage.loadFile('data://3str.cif').then(function (o) { + o.addRepresentation('licorice') + stage.autoView() +}) diff --git a/examples/examples/scripts/parser/ccp4.js b/examples/examples/scripts/parser/ccp4.js new file mode 100644 index 000000000..312d37cdf --- /dev/null +++ b/examples/examples/scripts/parser/ccp4.js @@ -0,0 +1,48 @@ + +stage.loadFile('data://3pqr.ccp4.gz').then(function (o) { + o.addRepresentation('surface', { + contour: true, + color: 'skyblue', + boxSize: 10 + }) + o.autoView() + + var position = new NGL.Vector3() + function getCenterArray () { + position.copy(stage.viewerControls.position) + return position.negate().toArray() + } + + var sphereBuffer = new NGL.SphereBuffer( + { + position: new Float32Array(getCenterArray()), + color: new Float32Array([ 1, 0, 0 ]), + radius: new Float32Array([ 1 ]) + }, + { disableImpostor: true } + ) + o.addBufferRepresentation(sphereBuffer, { flatShaded: true }) + + stage.viewerControls.signals.changed.add(function () { + sphereBuffer.setAttributes({ + position: getCenterArray() + }) + }) +}) + +// mode 0 data +stage.loadFile('data://3pqr-mode0.ccp4').then(function (o) { + o.addRepresentation('surface', { + contour: true, + color: 'tomato', + boxSize: 10 + }) + o.autoView() +}) + +stage.loadFile('data://3pqr.pdb').then(function (o) { + o.addRepresentation('line', { + linewidth: 5, colorValue: 'yellow' + }) + o.autoView() +}) diff --git a/examples/examples/scripts/parser/cif-chemComp.js b/examples/examples/scripts/parser/cif-chemComp.js new file mode 100644 index 000000000..294d5524f --- /dev/null +++ b/examples/examples/scripts/parser/cif-chemComp.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://PRDCC_000001.cif').then(function (o) { + o.addRepresentation('licorice', { sele: '/0', multipleBond: 'symmetric' }) + stage.autoView() +}) diff --git a/examples/examples/scripts/parser/cif-core.js b/examples/examples/scripts/parser/cif-core.js new file mode 100644 index 000000000..981edb32e --- /dev/null +++ b/examples/examples/scripts/parser/cif-core.js @@ -0,0 +1,14 @@ + +stage.setParameters({ + cameraType: 'orthographic', + clipDist: 0 +}) + +stage.loadFile('data://Fe2O3_mp-715572_conventional_standard.cif').then(function (o) { + o.addRepresentation('licorice') + o.addRepresentation('spacefill', { + radiusScale: 0.25 + }) + o.addRepresentation('unitcell') + stage.autoView() +}) diff --git a/examples/examples/scripts/parser/cif.js b/examples/examples/scripts/parser/cif.js new file mode 100644 index 000000000..7044648c2 --- /dev/null +++ b/examples/examples/scripts/parser/cif.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://3SN6.cif').then(function (o) { + o.addRepresentation('cartoon', { radius: 'sstruc' }) + o.autoView() +}) diff --git a/examples/examples/scripts/parser/cns.js b/examples/examples/scripts/parser/cns.js new file mode 100644 index 000000000..38ea034f3 --- /dev/null +++ b/examples/examples/scripts/parser/cns.js @@ -0,0 +1,12 @@ + +stage.loadFile('data://3pqr.cns').then(function (o) { + o.addRepresentation('surface', { + visible: true, isolevel: 2.0, opacity: 0.6 + }) + // o.autoView(); +}) + +stage.loadFile('data://3pqr.pdb').then(function (o) { + o.addRepresentation('cartoon') + o.autoView() +}) diff --git a/examples/examples/scripts/parser/cube-benzene.js b/examples/examples/scripts/parser/cube-benzene.js new file mode 100644 index 000000000..a69034aac --- /dev/null +++ b/examples/examples/scripts/parser/cube-benzene.js @@ -0,0 +1,25 @@ + +stage.loadFile('data://benzene-homo.cube').then(function (o) { + o.addRepresentation('surface', { + visible: true, + isolevelType: 'value', + isolevel: 0.01, + color: 'blue', + opacity: 0.7, + opaqueBack: false + }) + o.addRepresentation('surface', { + visible: true, + isolevelType: 'value', + isolevel: -0.01, + color: 'red', + opacity: 0.7, + opaqueBack: false + }) + o.autoView() +}) + +stage.loadFile('data://benzene.sdf').then(function (o) { + o.addRepresentation('licorice') + o.autoView() +}) diff --git a/examples/examples/scripts/parser/cube-big.js b/examples/examples/scripts/parser/cube-big.js new file mode 100644 index 000000000..37f41bc1d --- /dev/null +++ b/examples/examples/scripts/parser/cube-big.js @@ -0,0 +1,21 @@ + +Promise.all([ + stage.loadFile('data://rho-inactive_md-hydration.cube.gz'), + stage.loadFile('data://rho-inactive_md-system.gro') +]).then(function (oList) { + var o1 = oList[ 0 ] + var o2 = oList[ 1 ] + + o1.addRepresentation('surface', { isolevel: 2.7 }) + + o2.addRepresentation('cartoon') + o2.addRepresentation('licorice', { sele: 'hetero' }) + + var as = o2.structure.getAtomSetWithinVolume( + o1.volume, 2, o1.volume.getValueForSigma(2.7) + ) + var as2 = o2.structure.getAtomSetWithinGroup(as) + o2.addRepresentation('ball+stick', { sele: as2.toSeleString() }) + + stage.autoView() +}) diff --git a/examples/examples/scripts/parser/cube-bromobenzene.js b/examples/examples/scripts/parser/cube-bromobenzene.js new file mode 100644 index 000000000..5b4f23b51 --- /dev/null +++ b/examples/examples/scripts/parser/cube-bromobenzene.js @@ -0,0 +1,10 @@ + +stage.loadFile('data://bromobenzene-med.cube.gz').then(function (o) { + o.addRepresentation('surface', { opacity: 0.6 }) + stage.autoView() +}) + +stage.loadFile('data://bromobenzene.pdb').then(function (o) { + o.addRepresentation('ball+stick') + stage.autoView() +}) diff --git a/examples/examples/scripts/parser/cube-protein.js b/examples/examples/scripts/parser/cube-protein.js new file mode 100644 index 000000000..771760924 --- /dev/null +++ b/examples/examples/scripts/parser/cube-protein.js @@ -0,0 +1,7 @@ + +stage.loadFile('data://3ek3.cif', { defaultRepresentation: true }) + +stage.loadFile('data://3ek3-2fofc.cub').then(function (o) { + o.addRepresentation('surface', { opacity: 0.6 }) + o.autoView() +}) diff --git a/examples/examples/scripts/parser/cube.js b/examples/examples/scripts/parser/cube.js new file mode 100644 index 000000000..ef0518560 --- /dev/null +++ b/examples/examples/scripts/parser/cube.js @@ -0,0 +1,12 @@ + +stage.loadFile('data://acrolein1gs.cube.gz').then(function (o) { + o.addRepresentation('surface', { + visible: true, isolevel: 0.1, opacity: 0.6 + }) + o.autoView() +}) + +stage.loadFile('data://acrolein.pdb').then(function (o) { + o.addRepresentation('licorice') + o.autoView() +}) diff --git a/examples/examples/scripts/parser/dcd-large.js b/examples/examples/scripts/parser/dcd-large.js new file mode 100644 index 000000000..367fbc1ad --- /dev/null +++ b/examples/examples/scripts/parser/dcd-large.js @@ -0,0 +1,20 @@ + +stage.loadFile('data://md_1u19.gro').then(function (o) { + o.addRepresentation('cartoon') + o.addRepresentation('surface', { visible: false, lazy: true }) + o.autoView() + + NGL.autoLoad('data://md_1u19.dcd.gz').then(function (frames) { + o.addTrajectory(frames, { + initialFrame: 100, + defaultTimeout: 100, + defaultStep: undefined, + defaultInterpolateType: 'spline', + defaultDirection: 'forward', + centerPbc: false, + removePbc: false, + superpose: true, + sele: 'backbone and not hydrogen' + }) + }) +}) diff --git a/examples/examples/scripts/parser/dcd.js b/examples/examples/scripts/parser/dcd.js new file mode 100644 index 000000000..3ecf53eac --- /dev/null +++ b/examples/examples/scripts/parser/dcd.js @@ -0,0 +1,20 @@ + +stage.loadFile('data://ala3.pdb').then(function (o) { + var atomPair = [ + // [ "1.CA", "3.CA" ] + [ 8, 28 ] + ] + + o.addRepresentation('licorice') + o.addRepresentation('cartoon', { sele: 'protein' }) + o.addRepresentation('distance', { + atomPair: atomPair, + labelColor: 'skyblue', + color: 'skyblue' + }) + o.autoView() + + NGL.autoLoad('data://ala3.dcd').then(function (frames) { + o.addTrajectory(frames) + }) +}) diff --git a/examples/examples/scripts/parser/dsn6.js b/examples/examples/scripts/parser/dsn6.js new file mode 100644 index 000000000..8b7f9eb97 --- /dev/null +++ b/examples/examples/scripts/parser/dsn6.js @@ -0,0 +1,10 @@ + +stage.loadFile('data://3str-2fofc.dsn6').then(function (o) { + o.addRepresentation('surface', { wireframe: true, color: 'tomato' }) + stage.autoView() +}) + +stage.loadFile('data://3str.cif').then(function (o) { + o.addRepresentation('licorice') + stage.autoView() +}) diff --git a/examples/examples/scripts/parser/dx.js b/examples/examples/scripts/parser/dx.js new file mode 100644 index 000000000..add0941f2 --- /dev/null +++ b/examples/examples/scripts/parser/dx.js @@ -0,0 +1,26 @@ + +stage.loadFile('data://1crn_apbs_pot.dx.gz').then(function (o) { + o.addRepresentation('surface', { + isolevelType: 'value', + isolevel: -0.4, + smooth: 1, + color: 'red', + opacity: 0.6, + side: 'back', + useWorker: false, + opaqueBack: false + }) + + o.addRepresentation('surface', { + isolevelType: 'value', + isolevel: 0.4, + smooth: 1, + color: 'blue', + opacity: 0.6, + side: 'front', + useWorker: false, + opaqueBack: false + }) + + o.autoView() +}) diff --git a/examples/examples/scripts/parser/dxbin.js b/examples/examples/scripts/parser/dxbin.js new file mode 100644 index 000000000..b0df7c7fd --- /dev/null +++ b/examples/examples/scripts/parser/dxbin.js @@ -0,0 +1,51 @@ + +var promiseList = [ + stage.loadFile('data://3pqr.pqr'), + stage.loadFile('data://3pqr-pot.dxbin') +] + +Promise.all(promiseList).then(function (compList) { + var pqr = compList[ 0 ] + var dxbin = compList[ 1 ] + + pqr.addRepresentation('cartoon', { + colorScheme: 'bfactor', + colorScale: 'rwb', + colorDomain: [ -1, 0, 1 ] + }) + pqr.addRepresentation('licorice', { + colorScheme: 'bfactor', + colorScale: 'rwb', + colorDomain: [ -1, 0, 1 ] + }) + pqr.addRepresentation('surface', { + colorVolume: dxbin.volume, + colorScheme: 'volume', + colorScale: 'rwb', + colorDomain: [ -5, 0, 5 ] + }) + + pqr.autoView() + + dxbin.addRepresentation('surface', { + isolevelType: 'value', + isolevel: -1.5, + smooth: 1, + color: 'red', + opacity: 0.6, + side: 'back', + opaqueBack: false + }) + + dxbin.addRepresentation('surface', { + isolevelType: 'value', + isolevel: 1.5, + smooth: 1, + color: 'blue', + opacity: 0.6, + side: 'front', + opaqueBack: false + }) + + stage.autoView() +}) diff --git a/examples/examples/scripts/parser/gro-large.js b/examples/examples/scripts/parser/gro-large.js new file mode 100644 index 000000000..386ebaf04 --- /dev/null +++ b/examples/examples/scripts/parser/gro-large.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://water.gro').then(function (o) { + o.addRepresentation('line', { color: 'residueindex' }) + o.autoView() +}) diff --git a/examples/examples/scripts/parser/gro-trajectory.js b/examples/examples/scripts/parser/gro-trajectory.js new file mode 100644 index 000000000..f630086db --- /dev/null +++ b/examples/examples/scripts/parser/gro-trajectory.js @@ -0,0 +1,13 @@ + +stage.loadFile('data://md_1u19_trj.gro', { + asTrajectory: true, + sele: '50-100' +}).then(function (o) { + o.addTrajectory() + o.addRepresentation('cartoon') + o.addRepresentation('helixorient') + o.addRepresentation('line', { + sele: 'not hydrogen and sidechainAttached' + }) + stage.autoView() +}) diff --git a/examples/examples/scripts/parser/gro.js b/examples/examples/scripts/parser/gro.js new file mode 100644 index 000000000..a59cef908 --- /dev/null +++ b/examples/examples/scripts/parser/gro.js @@ -0,0 +1,6 @@ + +stage.loadFile('data://md.gro').then(function (o) { + o.addRepresentation('cartoon') + o.addRepresentation('line') + o.autoView() +}) diff --git a/examples/examples/scripts/parser/kin.js b/examples/examples/scripts/parser/kin.js new file mode 100644 index 000000000..d5c038528 --- /dev/null +++ b/examples/examples/scripts/parser/kin.js @@ -0,0 +1,47 @@ + +NGL.autoLoad('data://1crnFH-multi.kin').then(function (kinemage) { + for (let master in kinemage.masterDict) { + var shape = new NGL.Shape(master, { + pointSize: 3, + sizeAttenuation: false, + lineWidth: 3 + }) + + kinemage.dotLists.forEach(function (dotList) { + if (!dotList.masterArray.includes(master)) return + for (var i = 0, il = dotList.positionArray.length / 3; i < il; ++i) { + var i3 = i * 3 + var x = dotList.positionArray[ i3 ] + var y = dotList.positionArray[ i3 + 1 ] + var z = dotList.positionArray[ i3 + 2 ] + var r = dotList.colorArray[ i3 ] + var g = dotList.colorArray[ i3 + 1 ] + var b = dotList.colorArray[ i3 + 2 ] + shape.addPoint([ x, y, z ], [ r, g, b ], dotList.labelArray[ i ]) + } + }) + + kinemage.vectorLists.forEach(function (vectorList) { + if (!vectorList.masterArray.includes(master)) return + for (var i = 0, il = vectorList.position1Array.length / 3; i < il; ++i) { + var i3 = i * 3 + var x1 = vectorList.position1Array[ i3 ] + var y1 = vectorList.position1Array[ i3 + 1 ] + var z1 = vectorList.position1Array[ i3 + 2 ] + var x2 = vectorList.position2Array[ i3 ] + var y2 = vectorList.position2Array[ i3 + 1 ] + var z2 = vectorList.position2Array[ i3 + 2 ] + var r = vectorList.color1Array[ i3 ] + var g = vectorList.color1Array[ i3 + 1 ] + var b = vectorList.color1Array[ i3 + 2 ] + shape.addWideline([ x1, y1, z1 ], [ x2, y2, z2 ], [ r, g, b ], vectorList.label1Array[ i ]) + } + }) + + var visible = kinemage.masterDict[ master ].visible + var shapeComp = stage.addComponentFromObject(shape, { visible: visible }) + shapeComp.addRepresentation('buffer') + } + + stage.autoView() +}) diff --git a/examples/examples/scripts/parser/map.js b/examples/examples/scripts/parser/map.js new file mode 100644 index 000000000..c6ef8d229 --- /dev/null +++ b/examples/examples/scripts/parser/map.js @@ -0,0 +1,13 @@ + +stage.loadFile('data://emd_2682.map.gz').then(function (o) { + o.addRepresentation('surface', { + opacity: 0.5, + opaqueBack: true + }) + stage.autoView() +}) + +stage.loadFile('data://4UJD.cif.gz').then(function (o) { + o.addRepresentation('cartoon', { color: 'chainindex' }) + stage.autoView() +}) diff --git a/examples/examples/scripts/parser/mmtf-reduced.js b/examples/examples/scripts/parser/mmtf-reduced.js new file mode 100644 index 000000000..5f03a3b6b --- /dev/null +++ b/examples/examples/scripts/parser/mmtf-reduced.js @@ -0,0 +1,2 @@ + +stage.loadFile('data://1stp.bb.mmtf', { defaultRepresentation: true }) diff --git a/examples/examples/scripts/parser/mmtf.js b/examples/examples/scripts/parser/mmtf.js new file mode 100644 index 000000000..3a2854868 --- /dev/null +++ b/examples/examples/scripts/parser/mmtf.js @@ -0,0 +1,6 @@ + +stage.loadFile('data://1blu.mmtf').then(function (o) { + o.addRepresentation('cartoon', { color: 'residueindex' }) + o.addRepresentation('ball+stick', { sele: 'ligand' }) + o.autoView() +}) diff --git a/examples/examples/scripts/parser/mol2.js b/examples/examples/scripts/parser/mol2.js new file mode 100644 index 000000000..45fa10288 --- /dev/null +++ b/examples/examples/scripts/parser/mol2.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://adrenalin.mol2').then(function (o) { + o.addRepresentation('hyperball') + o.autoView() +}) diff --git a/examples/examples/scripts/parser/mrc.js b/examples/examples/scripts/parser/mrc.js new file mode 100644 index 000000000..f8c08d377 --- /dev/null +++ b/examples/examples/scripts/parser/mrc.js @@ -0,0 +1,2 @@ + +stage.loadFile('data://betaGal.mrc', { defaultRepresentation: true }) diff --git a/examples/examples/scripts/parser/nctraj.js b/examples/examples/scripts/parser/nctraj.js new file mode 100644 index 000000000..8e8af4803 --- /dev/null +++ b/examples/examples/scripts/parser/nctraj.js @@ -0,0 +1,9 @@ + +stage.loadFile('data://DPDP.pdb').then(function (o) { + o.addRepresentation('licorice') + o.autoView() + + NGL.autoLoad('data://DPDP.nc').then(function (frames) { + o.addTrajectory(frames) + }) +}) diff --git a/examples/examples/scripts/parser/obj.js b/examples/examples/scripts/parser/obj.js new file mode 100644 index 000000000..97409eb43 --- /dev/null +++ b/examples/examples/scripts/parser/obj.js @@ -0,0 +1,11 @@ + +stage.loadFile('data://1crn.pdb').then(function (o) { + o.addRepresentation('spacefill') + o.autoView() +}) + +stage.loadFile('data://1crn.obj').then(function (o) { + o.addRepresentation('surface', { + opacity: 0.7, side: 'double' + }) +}) diff --git a/examples/examples/scripts/parser/pdb.js b/examples/examples/scripts/parser/pdb.js new file mode 100644 index 000000000..658f9012b --- /dev/null +++ b/examples/examples/scripts/parser/pdb.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://1blu.pdb').then(function (o) { + o.addRepresentation('cartoon') + o.autoView() +}) diff --git a/examples/examples/scripts/parser/pdbqt.js b/examples/examples/scripts/parser/pdbqt.js new file mode 100644 index 000000000..3e79b499f --- /dev/null +++ b/examples/examples/scripts/parser/pdbqt.js @@ -0,0 +1,9 @@ + +stage.loadFile('data://dxc.pdbqt', { + sele: '/0 or /1 or /2' +}).then(function (o) { + o.addRepresentation('licorice', { + colorScheme: 'partialCharge' + }) + stage.autoView() +}) diff --git a/examples/examples/scripts/parser/ply.js b/examples/examples/scripts/parser/ply.js new file mode 100644 index 000000000..53da45f57 --- /dev/null +++ b/examples/examples/scripts/parser/ply.js @@ -0,0 +1,12 @@ + +stage.loadFile('data://1crn.pdb').then(function (o) { + o.addRepresentation('cartoon') + o.addRepresentation('ball+stick') + o.autoView() +}) + +stage.loadFile('data://1crn.ply').then(function (o) { + o.addRepresentation('surface', { + opacity: 0.3, side: 'double' + }) +}) diff --git a/examples/examples/scripts/parser/pqr-explicit-radii.js b/examples/examples/scripts/parser/pqr-explicit-radii.js new file mode 100644 index 000000000..125cd739e --- /dev/null +++ b/examples/examples/scripts/parser/pqr-explicit-radii.js @@ -0,0 +1,16 @@ + +stage.loadFile('data://1crn_apbs.pqr').then(function (o) { + o.addRepresentation('spacefill', { + radiusType: 'explicit', + colorScheme: 'partialCharge', + visible: false + }) + o.addRepresentation('surface', { + surfaceType: 'av', + colorScheme: 'electrostatic', + scaleFactor: 3.0, + opacity: 1.0, + radiusType: 'explicit' + }) + o.autoView() +}) diff --git a/examples/examples/scripts/parser/pqr.js b/examples/examples/scripts/parser/pqr.js new file mode 100644 index 000000000..c1d2056c3 --- /dev/null +++ b/examples/examples/scripts/parser/pqr.js @@ -0,0 +1,9 @@ + +stage.loadFile('data://1crn_apbs.pqr').then(function (o) { + o.addRepresentation('cartoon') + o.addRepresentation('licorice', { + colorScheme: 'partialCharge', + colorScale: 'rwb' + }) + o.autoView() +}) diff --git a/examples/examples/scripts/parser/prmtop.js b/examples/examples/scripts/parser/prmtop.js new file mode 100644 index 000000000..a852e83f1 --- /dev/null +++ b/examples/examples/scripts/parser/prmtop.js @@ -0,0 +1,14 @@ + +stage.loadFile('data://DPDP.prmtop').then(function (o) { + NGL.autoLoad('data://DPDP.nc').then(function (frames) { + o.addTrajectory(frames, { + initialFrame: 0, + deltaTime: 200 + }) + o.addRepresentation('licorice', {scale: 0.5}) + o.addRepresentation('spacefill', {sele: 'not :B'}) + o.addRepresentation('cartoon') + o.addRepresentation('backbone') + stage.autoView() + }) +}) diff --git a/examples/examples/scripts/parser/psf.js b/examples/examples/scripts/parser/psf.js new file mode 100644 index 000000000..54a2af0fb --- /dev/null +++ b/examples/examples/scripts/parser/psf.js @@ -0,0 +1,12 @@ + +stage.loadFile('data://ala3.psf').then(function (o) { + NGL.autoLoad('data://ala3.dcd').then(function (frames) { + o.addTrajectory(frames, { + initialFrame: 0, + superpose: false + }) + o.addRepresentation('licorice', {scale: 0.5}) + o.addRepresentation('backbone') + stage.autoView() + }) +}) diff --git a/examples/examples/scripts/parser/sdf-models.js b/examples/examples/scripts/parser/sdf-models.js new file mode 100644 index 000000000..36a40744c --- /dev/null +++ b/examples/examples/scripts/parser/sdf-models.js @@ -0,0 +1,33 @@ + +function addElement (el) { + Object.assign(el.style, { + position: 'absolute', + zIndex: 10 + }) + stage.viewer.container.appendChild(el) +} + +function createElement (name, properties, style) { + var el = document.createElement(name) + Object.assign(el, properties) + Object.assign(el.style, style) + return el +} + +stage.loadFile('data://ligands.sd').then(function (o) { + o.setSelection('/0') + o.addRepresentation('licorice') + o.autoView() + + var modelRange = createElement('input', { + type: 'range', + value: 0, + min: 0, + max: o.structure.modelStore.count - 1, + step: 1 + }, { top: '12px', left: '12px' }) + modelRange.oninput = function (e) { + o.setSelection('/' + e.target.value) + } + addElement(modelRange) +}) diff --git a/examples/examples/scripts/parser/sdf.js b/examples/examples/scripts/parser/sdf.js new file mode 100644 index 000000000..5263a19c7 --- /dev/null +++ b/examples/examples/scripts/parser/sdf.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://adrenalin.sdf').then(function (o) { + o.addRepresentation('hyperball') + o.autoView() +}) diff --git a/examples/examples/scripts/parser/top.js b/examples/examples/scripts/parser/top.js new file mode 100644 index 000000000..a5181d05f --- /dev/null +++ b/examples/examples/scripts/parser/top.js @@ -0,0 +1,15 @@ + +stage.loadFile('data://gpcr.top').then(function (o) { + NGL.autoLoad('data://gpcr.xtc').then(function (frames) { + o.addTrajectory(frames, { + initialFrame: 0, + centerPbc: true, + removePbc: true + }) + o.addRepresentation('cartoon') + o.addRepresentation('backbone') + o.addRepresentation('licorice', {sele: 'protein and not _h'}) + o.addRepresentation('line', {sele: 'popc and not _h'}) + stage.autoView() + }) +}) diff --git a/examples/examples/scripts/parser/trr.js b/examples/examples/scripts/parser/trr.js new file mode 100644 index 000000000..8a77b3948 --- /dev/null +++ b/examples/examples/scripts/parser/trr.js @@ -0,0 +1,9 @@ + +stage.loadFile('data://md.gro').then(function (o) { + o.addRepresentation('cartoon') + o.autoView() + + NGL.autoLoad('data://md.trr').then(function (frames) { + o.addTrajectory(frames) + }) +}) diff --git a/examples/examples/scripts/parser/validation.js b/examples/examples/scripts/parser/validation.js new file mode 100644 index 000000000..c6365b176 --- /dev/null +++ b/examples/examples/scripts/parser/validation.js @@ -0,0 +1,18 @@ + +Promise.all([ + stage.loadFile('data://3PQR.cif'), + NGL.autoLoad('data://3pqr_validation.xml', { ext: 'validation' }) +]).then(function (ol) { + ol[ 0 ].structure.validation = ol[ 1 ] + ol[ 0 ].addRepresentation('cartoon', { color: 'geoquality' }) + ol[ 0 ].addRepresentation('validation') + ol[ 0 ].addRepresentation('ball+stick', { + sele: ol[ 1 ].clashSele, + color: 'geoquality' + }) + ol[ 0 ].addRepresentation('licorice', { + sele: 'hetero', + color: 'geoquality' + }) + stage.autoView() +}) diff --git a/examples/examples/scripts/parser/xtc.js b/examples/examples/scripts/parser/xtc.js new file mode 100644 index 000000000..b47e88a49 --- /dev/null +++ b/examples/examples/scripts/parser/xtc.js @@ -0,0 +1,9 @@ + +stage.loadFile('data://md.gro').then(function (o) { + o.addRepresentation('cartoon') + o.autoView() + + NGL.autoLoad('data://md.xtc').then(function (frames) { + o.addTrajectory(frames) + }) +}) diff --git a/examples/examples/scripts/representation/angle.js b/examples/examples/scripts/representation/angle.js new file mode 100644 index 000000000..26f8ab075 --- /dev/null +++ b/examples/examples/scripts/representation/angle.js @@ -0,0 +1,16 @@ + +stage.loadFile('data://1blu.pdb').then(function (o) { + var atomTriple = [ + [ 2, 6, 9 ], + [ '2.CA', '2.C', '2.O' ] + ] + + o.addRepresentation('ball+stick', {sele: '1-2'}) + o.addRepresentation('angle', { + atomTriple: atomTriple, + labelSize: 1.0, + sdf: false + }) + + stage.autoView() +}) diff --git a/examples/examples/scripts/representation/axes.js b/examples/examples/scripts/representation/axes.js new file mode 100644 index 000000000..7ebba35d6 --- /dev/null +++ b/examples/examples/scripts/representation/axes.js @@ -0,0 +1,16 @@ + +stage.loadFile('rcsb://3pqr.mmtf', { + defaultAssembly: 'BU1' +}).then(function (o) { + o.addRepresentation('cartoon') + o.addRepresentation('axes', { + sele: 'RET', showAxes: false, showBox: true, radius: 0.2 + }) + o.addRepresentation('ball+stick', { sele: 'RET' }) + o.addRepresentation('axes', { + sele: ':B and backbone', showAxes: false, showBox: true, radius: 0.2 + }) + stage.autoView() + var pa = o.structure.getPrincipalAxes() + stage.animationControls.rotate(pa.getRotationQuaternion(), 1500) +}) diff --git a/examples/examples/scripts/representation/ball+stick.js b/examples/examples/scripts/representation/ball+stick.js new file mode 100644 index 000000000..5d86c3837 --- /dev/null +++ b/examples/examples/scripts/representation/ball+stick.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://1crn.pdb').then(function (o) { + o.addRepresentation('ball+stick') + o.autoView() +}) diff --git a/examples/examples/scripts/representation/contact.js b/examples/examples/scripts/representation/contact.js new file mode 100644 index 000000000..40c3ed600 --- /dev/null +++ b/examples/examples/scripts/representation/contact.js @@ -0,0 +1,71 @@ + +// create tooltip element and add to document body +var tooltip = document.createElement('div') +Object.assign(tooltip.style, { + display: 'none', + position: 'fixed', + zIndex: 10, + pointerEvents: 'none', + backgroundColor: 'rgba( 0, 0, 0, 0.6 )', + color: 'lightgrey', + padding: '8px', + fontFamily: 'sans-serif' +}) +document.body.appendChild(tooltip) + +// remove default hoverPick mouse action +stage.mouseControls.remove('hoverPick') + +// listen to `hovered` signal to move tooltip around and change its text +stage.signals.hovered.add(function (pickingProxy) { + if (pickingProxy) { + if (pickingProxy.atom || pickingProxy.bond) { + var atom = pickingProxy.atom || pickingProxy.closestBondAtom + var vm = atom.structure.data['@valenceModel'] + if (vm && vm.idealValence) { + tooltip.innerHTML = `${pickingProxy.getLabel()}
+
+ Atom: ${atom.qualifiedName()}
+ ideal valence: ${vm.idealValence[atom.index]}
+ ideal geometry: ${vm.idealGeometry[atom.index]}
+ implicit charge: ${vm.implicitCharge[atom.index]}
+ formal charge: ${atom.formalCharge === null ? '?' : atom.formalCharge}
+ ` + } else if (vm && vm.charge) { + tooltip.innerHTML = `${pickingProxy.getLabel()}
+
+ Atom: ${atom.qualifiedName()}
+ vm charge: ${vm.charge[atom.index]}
+ vm implicitH: ${vm.implicitH[atom.index]}
+ vm totalH: ${vm.totalH[atom.index]}
+ vm geom: ${vm.idealGeometry[atom.index]}
+ formal charge: ${atom.formalCharge === null ? '?' : atom.formalCharge}
+ ` + } else { + tooltip.innerHTML = `${pickingProxy.getLabel()}` + } + } else { + tooltip.innerHTML = `${pickingProxy.getLabel()}` + } + var mp = pickingProxy.mouse.position + tooltip.style.bottom = window.innerHeight - mp.y + 3 + 'px' + tooltip.style.left = mp.x + 3 + 'px' + tooltip.style.display = 'block' + } else { + tooltip.style.display = 'none' + } +}) + +stage.loadFile('rcsb://1crn').then(function (o) { + o.addRepresentation('cartoon', { + colorScheme: 'sstruc' + }) + o.addRepresentation('contact', { + backboneHydrogenBond: true + }) + o.addRepresentation('licorice', { + multipleBond: 'symmetric', + sele: 'not water' + }) + stage.autoView() +}) diff --git a/examples/examples/scripts/representation/dihedral.js b/examples/examples/scripts/representation/dihedral.js new file mode 100644 index 000000000..85e8c5ed1 --- /dev/null +++ b/examples/examples/scripts/representation/dihedral.js @@ -0,0 +1,21 @@ + +stage.loadFile('data://1blu.pdb').then(function (o) { + var atomQuad = [ + [2, 5, 6, 9], + ['1.C', '1.N', '1.CA', '1.CB'], + ['3.CB', '3.CA', '3.N', '3.C'] + // ['1.N', '1.C', '1.CB', '1.CA'] + ] + + o.addRepresentation('ball+stick', {sele: '1-3'}) + o.addRepresentation('dihedral', { + atomQuad: atomQuad, + sdf: false, + labelSize: 1.0, + labelColor: 'skyblue', + colorValue: 'red', + sectorOpacity: 0.75 + }) + + o.autoView() +}) diff --git a/examples/examples/scripts/representation/distance.js b/examples/examples/scripts/representation/distance.js new file mode 100644 index 000000000..0a5c407f0 --- /dev/null +++ b/examples/examples/scripts/representation/distance.js @@ -0,0 +1,16 @@ + +stage.loadFile('data://1blu.pdb').then(function (o) { + var atomPair = [ + [ '1.CA', '10.CA' ], + [ 1, 209 ] + ] + + o.addRepresentation('cartoon') + o.addRepresentation('distance', { + atomPair: atomPair, + color: 'skyblue', + labelUnit: 'nm' + }) + + o.autoView() +}) diff --git a/examples/examples/scripts/representation/helixorient.js b/examples/examples/scripts/representation/helixorient.js new file mode 100644 index 000000000..1244c046e --- /dev/null +++ b/examples/examples/scripts/representation/helixorient.js @@ -0,0 +1,13 @@ + +stage.loadFile('data://3dqb.pdb').then(function (o) { + // o.addRepresentation( "crossing", { + // ssBorder: true, radius: 0.6 + // } ); + // o.addRepresentation( "rope", { + // radius: 0.2 + // } ); + o.addRepresentation('cartoon') + o.addRepresentation('helixorient') + + o.autoView() +}) diff --git a/examples/examples/scripts/representation/hyperball.js b/examples/examples/scripts/representation/hyperball.js new file mode 100644 index 000000000..c662287e1 --- /dev/null +++ b/examples/examples/scripts/representation/hyperball.js @@ -0,0 +1,6 @@ + +stage.loadFile('data://1crn.pdb').then(function (o) { + o.addRepresentation('cartoon') + o.addRepresentation('hyperball', { sele: 'sidechainAttached' }) + o.autoView() +}) diff --git a/examples/examples/scripts/representation/label.js b/examples/examples/scripts/representation/label.js new file mode 100644 index 000000000..206ef1396 --- /dev/null +++ b/examples/examples/scripts/representation/label.js @@ -0,0 +1,19 @@ + +stage.loadFile('data://1crn.pdb').then(function (o) { + o.addRepresentation('tube', { radius: 'sstruc' }) + o.addRepresentation('ball+stick', { sele: 'sidechainAttached' }) + o.addRepresentation('label', { + sele: '.CA', + color: 'element', + labelType: 'format', + labelFormat: '%(resname)s %(chainname)s%(resno)s' + }) + o.autoView() +}) + +stage.loadFile('data://1crn.ply').then(function (o) { + o.addRepresentation('surface', { + opacity: 0.3, + side: 'front' + }) +}) diff --git a/examples/examples/scripts/representation/licorice.js b/examples/examples/scripts/representation/licorice.js new file mode 100644 index 000000000..73af9bf43 --- /dev/null +++ b/examples/examples/scripts/representation/licorice.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://1crn.pdb').then(function (o) { + o.addRepresentation('licorice') + o.autoView() +}) diff --git a/examples/examples/scripts/representation/line-and-cross.js b/examples/examples/scripts/representation/line-and-cross.js new file mode 100644 index 000000000..dd2d437b3 --- /dev/null +++ b/examples/examples/scripts/representation/line-and-cross.js @@ -0,0 +1,8 @@ +stage.loadFile('data://1blu.mmtf').then(function (o) { + o.addRepresentation('line', { + lines: true, + crosses: `lone`, + crossSize: 0.35 + }) + o.autoView() +}) diff --git a/examples/examples/scripts/representation/line.js b/examples/examples/scripts/representation/line.js new file mode 100644 index 000000000..05940cd18 --- /dev/null +++ b/examples/examples/scripts/representation/line.js @@ -0,0 +1,16 @@ + +stage.loadFile('data://1crn.pdb').then(function (o) { + o.addRepresentation('ribbon') + o.addRepresentation('line', { + sele: 'sidechainAttached', + linewidth: 7 + }) + o.addRepresentation('point', { + sele: 'sidechainAttached', + sizeAttenuation: false, + pointSize: 7, + alphaTest: 1, + useTexture: true + }) + o.autoView() +}) diff --git a/examples/examples/scripts/representation/molecularsurface-av.js b/examples/examples/scripts/representation/molecularsurface-av.js new file mode 100644 index 000000000..df3011eca --- /dev/null +++ b/examples/examples/scripts/representation/molecularsurface-av.js @@ -0,0 +1,31 @@ + +stage.loadFile('data://2vts.mmtf').then(function (o) { + o.addRepresentation('line', { sele: 'not hetero' }) + o.addRepresentation('licorice', { + multipleBond: 'symmetric', + sele: 'hetero and (not water)' + }) + o.addRepresentation('surface', { + sele: 'hetero and (not water)', + surfaceType: 'av', + contour: true, + colorScheme: 'element', + colorValue: '#0f0', + useWorker: false + }) + o.addRepresentation('surface', { + sele: 'not hetero', + surfaceType: 'av', + colorScheme: 'bfactor', + contour: true, + filterSele: '10 OR 11 OR 12 OR 13 OR 14 OR 18 OR 31 OR 33 OR ' + + '64 OR 80 OR 81 OR 82 OR 83 OR 84 OR 85 OR 86 OR ' + + '129 OR 131 OR 132 OR 134 OR 144 OR 145' + }) + stage.viewerControls.orient([ + -25.08, 20.9, -12.01, 0, + 3.52, -13.97, -31.66, 0, + -23.85, -24.05, 7.95, 0, + -27.16, -8.65, -63.38, 1 + ]) +}) diff --git a/examples/examples/scripts/representation/molecularsurface-filter.js b/examples/examples/scripts/representation/molecularsurface-filter.js new file mode 100644 index 000000000..067c5b510 --- /dev/null +++ b/examples/examples/scripts/representation/molecularsurface-filter.js @@ -0,0 +1,43 @@ + +// stage.loadFile( "data://3pqr.pdb" ).then( function( o ){ +// stage.loadFile( "rcsb://4cup" ).then( function( o ){ +stage.loadFile('rcsb://4hhb').then(function (o) { + // var ligSele = "RET"; + // var ligSele = "ZYB"; + var ligSele = 'HEM and :B' + var sview = o.structure.getView(new NGL.Selection(ligSele)) + var filterSet = o.structure.getAtomSetWithinSelection(new NGL.Selection(ligSele), 7) + var filterSet2 = o.structure.getAtomSetWithinSelection(new NGL.Selection(ligSele), 5) + var groupSet = o.structure.getAtomSetWithinGroup(filterSet2) + + o.addRepresentation('licorice', { + sele: groupSet.toSeleString() + }) + o.addRepresentation('ball+stick', { + sele: ligSele + }) + + o.addRepresentation('surface', { + sele: 'polymer', + surfaceType: 'ms', + colorScheme: 'uniform', + opacity: 0.7, + opaqueBack: false, + useWorker: false, + clipCenter: sview.center, + filterSele: filterSet.toSeleString() + // filterSele: groupSet.toSeleString() + }) + + o.addRepresentation('surface', { + sele: 'polymer', + surfaceType: 'ms', + color: 'lime', + opacity: 0.7, + wireframe: true, + clipRadius: sview.boundingBox.getSize(new NGL.Vector3()).length() / 2 + 5, + clipCenter: sview.center + }) + + stage.autoView() +}) diff --git a/examples/examples/scripts/representation/molecularsurface.js b/examples/examples/scripts/representation/molecularsurface.js new file mode 100644 index 000000000..14e3b1a10 --- /dev/null +++ b/examples/examples/scripts/representation/molecularsurface.js @@ -0,0 +1,14 @@ + +stage.loadFile('data://1crn.pdb').then(function (o) { + o.addRepresentation('surface', { + surfaceType: 'ms', + smooth: 2, + probeRadius: 1.4, + scaleFactor: 2.0, + flatShaded: false, + opacity: 0.7, + lowResolution: false, + colorScheme: 'element' + }) + o.autoView() +}) diff --git a/examples/examples/scripts/representation/point.js b/examples/examples/scripts/representation/point.js new file mode 100644 index 000000000..8fe4ca5e9 --- /dev/null +++ b/examples/examples/scripts/representation/point.js @@ -0,0 +1,16 @@ + +stage.loadFile('data://1crn.pdb').then(function (o) { + o.addRepresentation('licorice') + o.addRepresentation('point', { + sele: '*', + sizeAttenuation: true, + pointSize: 7, + opacity: 0.6, + useTexture: true, + alphaTest: 0.0, + edgeBleach: 1.0, + forceTransparent: true, + sortParticles: true + }) + o.autoView() +}) diff --git a/examples/examples/scripts/representation/representation-lazy.js b/examples/examples/scripts/representation/representation-lazy.js new file mode 100644 index 000000000..712deb051 --- /dev/null +++ b/examples/examples/scripts/representation/representation-lazy.js @@ -0,0 +1,6 @@ + +stage.loadFile('rcsb://3pqr.mmtf').then(function (o) { + o.addRepresentation('cartoon') + o.addRepresentation('surface', { visible: false, lazy: true }) + stage.autoView() +}) diff --git a/examples/examples/scripts/representation/rocket.js b/examples/examples/scripts/representation/rocket.js new file mode 100644 index 000000000..fca7beca4 --- /dev/null +++ b/examples/examples/scripts/representation/rocket.js @@ -0,0 +1,6 @@ + +stage.loadFile('data://1crn.pdb').then(function (o) { + o.addRepresentation('cartoon') + o.addRepresentation('rocket') + o.autoView() +}) diff --git a/examples/examples/scripts/representation/slice.js b/examples/examples/scripts/representation/slice.js new file mode 100644 index 000000000..255d93a91 --- /dev/null +++ b/examples/examples/scripts/representation/slice.js @@ -0,0 +1,19 @@ + +Promise.all([ + stage.loadFile('data://3pqr.ccp4.gz'), + stage.loadFile('data://3pqr.pdb') +]).then(function (ol) { + var sele = new NGL.Selection('245:A.NZ') + + ol[ 0 ].addRepresentation('slice', { + dimension: 'z', + positionType: 'coordinate', + position: ol[ 1 ].structure.getView(sele).center.z + }) + ol[ 0 ].addRepresentation('surface') + + ol[ 1 ].addRepresentation('licorice') + ol[ 1 ].addRepresentation('cartoon') + + stage.autoView() +}) diff --git a/examples/examples/scripts/representation/spacefill.js b/examples/examples/scripts/representation/spacefill.js new file mode 100644 index 000000000..3513c2fb1 --- /dev/null +++ b/examples/examples/scripts/representation/spacefill.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://1crn.pdb').then(function (o) { + o.addRepresentation('spacefill') + o.autoView() +}) diff --git a/examples/examples/scripts/representation/trace.js b/examples/examples/scripts/representation/trace.js new file mode 100644 index 000000000..1c53c5ed0 --- /dev/null +++ b/examples/examples/scripts/representation/trace.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://1crn.pdb').then(function (o) { + o.addRepresentation('trace') + o.autoView() +}) diff --git a/examples/examples/scripts/representation/tube-bfactor.js b/examples/examples/scripts/representation/tube-bfactor.js new file mode 100644 index 000000000..072dabfc9 --- /dev/null +++ b/examples/examples/scripts/representation/tube-bfactor.js @@ -0,0 +1,19 @@ + +stage.loadFile('data://1u19.pdb').then(function (o) { + o.addRepresentation('tube', { + sele: ':A', + radiusType: 'bfactor', + radiusScale: 0.010, + color: 'bfactor', + colorScale: 'RdYlBu' + }) + + o.addRepresentation('ball+stick', { + sele: ':A and sidechainAttached', + aspectRatio: 1.5, + color: 'bfactor', + colorScale: 'RdYlBu' + }) + + o.autoView(':A') +}) diff --git a/examples/examples/scripts/representation/unitcell.js b/examples/examples/scripts/representation/unitcell.js new file mode 100644 index 000000000..7b64d8aef --- /dev/null +++ b/examples/examples/scripts/representation/unitcell.js @@ -0,0 +1,9 @@ + +stage.loadFile('data://3pqr.pdb').then(function (o) { + o.addRepresentation('cartoon') + o.addRepresentation('unitcell') + o.addRepresentation('ribbon', { + assembly: 'UNITCELL', color: 0x00DD11, scale: 0.9 + }) + stage.autoView() +}) diff --git a/examples/examples/scripts/selection/aromatic.js b/examples/examples/scripts/selection/aromatic.js new file mode 100644 index 000000000..6265e9477 --- /dev/null +++ b/examples/examples/scripts/selection/aromatic.js @@ -0,0 +1,8 @@ + +stage.loadFile('data://3pqr.pdb').then(function (o) { + o.addRepresentation('line') + o.addRepresentation('licorice', { radius: 0.3, sele: 'ring' }) + o.addRepresentation('spacefill', { radius: 0.5, sele: 'aromaticRing' }) + + stage.autoView() +}) diff --git a/examples/examples/scripts/selection/basic.js b/examples/examples/scripts/selection/basic.js new file mode 100644 index 000000000..0edeee489 --- /dev/null +++ b/examples/examples/scripts/selection/basic.js @@ -0,0 +1,8 @@ + +stage.loadFile('data://1crn.pdb').then(function (o) { + var sele = 'not backbone or .CA or (PRO and .N)' + + o.addRepresentation('cartoon') + o.addRepresentation('licorice', { sele: sele }) + o.autoView() +}) diff --git a/examples/examples/scripts/selection/bonded.js b/examples/examples/scripts/selection/bonded.js new file mode 100644 index 000000000..230833cd9 --- /dev/null +++ b/examples/examples/scripts/selection/bonded.js @@ -0,0 +1,12 @@ + +stage.loadFile('data://1blu.mmtf').then(function (o) { + o.addRepresentation('cartoon') + + o.addRepresentation('ball+stick') + + o.addRepresentation('spacefill', { + sele: 'not bonded', opacity: 0.6 + }) + + stage.autoView() +}) diff --git a/examples/examples/scripts/selection/component.js b/examples/examples/scripts/selection/component.js new file mode 100644 index 000000000..94698c22b --- /dev/null +++ b/examples/examples/scripts/selection/component.js @@ -0,0 +1,14 @@ + +stage.loadFile('data://3pqr.pdb').then(function (o) { + o.addRepresentation('trace', {}, true) + var cartoon = o.addRepresentation('cartoon', {}, true) + var licorice = o.addRepresentation('spacefill', { + color: 'element', sele: 'TYR' + }, true) + + o.autoView() + + o.setSelection('1-90') + cartoon.setSelection('4-50') + licorice.setSelection('PRO') +}) diff --git a/examples/examples/scripts/selection/large.js b/examples/examples/scripts/selection/large.js new file mode 100644 index 000000000..ec172a467 --- /dev/null +++ b/examples/examples/scripts/selection/large.js @@ -0,0 +1,27 @@ + +// Add new color scheme byElement +var flatSyntax = '( 339:O/0 OR 76:O/0 OR 278:H/0 OR 143:H/0 OR 335:M/0 OR 196:M/0 OR 669:N/0 OR 389:N/0 OR 112:L/0 OR 192:M/0 OR 267:M/0 OR 104:C/0 OR 225:B/0 OR 225:b/0 OR 155:c/0 OR 237:O/0 OR 44:I/0 OR 175:I/0 OR 30:N/0 OR 315:N/0 OR 327:O/0 OR 139:I/0 OR 187:I/0 OR 141:T/0 OR 53:T/0 OR 39:M/0 OR 335:M/0 OR 81:X/0 OR 785:N/0 OR 5:I/0 OR 195:C/0 OR 96:C/0 OR 214:c/0 OR 117:c/0 OR 249:J/0 OR 133:M/0 OR 124:M/0 OR 138:Q/0 OR 77:Q/0 OR 404:Q/0 OR 144:Q/0 OR 110:H/0 OR 204:J/0 OR 109:E/0 OR 49:H/0 OR 48:e/0 OR 31:K/0 OR 15:J/0 OR 99:V/0 OR 154:V/0 OR 32:A/0 OR 109:A/0 OR 17:a/0 OR 120:a/0 OR 278:K/0 OR 40:L/0 OR 59:l/0 OR 27:l/0 OR 71:7/0 OR 112:7/0 OR 638:N/0 OR 269:N/0 OR 339:R/0 OR 34:R/0 OR 274:N/0 OR 175:J/0 OR 145:M/0 OR 70:L/0 OR 66:K/0 OR 6:M/0 OR 140:Q/0 OR 101:A/0 OR 81:h/0 OR 101:3/0 OR 131:a/0 OR 43:X/0 OR 44:N/0 OR 82:V/0 OR 43:V/0 OR 524:Z/0 OR 171:O/0 OR 383:R/0 OR 248:R/0 OR 49:H/0 OR 52:J/0 OR 181:D/0 OR 202:D/0 OR 130:d/0 OR 73:d/0 OR 113:Q/0 OR 166:A/0 OR 221:A/0 OR 59:a/0 OR 177:a/0 OR 321:H/0 OR 257:L/0 OR 197:L/0 OR 255:J/0 OR 86:J/0 OR 329:K/0 OR 27:I/0 OR 188:V/0 OR 56:U/0 OR 401:Q/0 OR 136:Q/0 OR 317:L/0 OR 199:J/0 OR 127:J/0 OR 356:M/0 OR 404:P/0 OR 33:k/0 OR 80:j/0 OR 90:5/0 OR 30:6/0 OR 12:U/0 OR 174:k/0 OR 92:6/0 OR 162:M/0 OR 328:M/0 OR 346:K/0 OR 148:C/0 OR 99:C/0 OR 61:c/0 OR 44:c/0 OR 162:J/0 OR 85:A/0 OR 68:a/0 OR 329:H/0 OR 101:L/0 OR 136:N/0 OR 666:N/0 OR 69:k/0 OR 72:k/0 OR 85:6/0 OR 181:6/0 OR 73:K/0 OR 34:O/0 OR 354:O/0 OR 235:K/0 OR 52:V/0 OR 276:K/0 OR 113:K/0 OR 345:R/0 OR 364:R/0 OR 79:L/0 OR 48:U/0 OR 302:J/0 OR 252:S/0 OR 355:R/0 OR 138:U/0 OR 313:M/0 OR 108:L/0 OR 105:B/0 OR 110:B/0 OR 121:b/0 OR 30:b/0 OR 28:K/0 OR 227:K/0 OR 159:N/0 OR 194:S/0 OR 8:L/0 OR 70:O/0 OR 106:P/0 OR 29:K/0 OR 358:R/0 OR 354:J/0 OR 219:P/0 OR 112:P/0 OR 720:N/0 OR 490:N/0 OR 261:T/0 OR 182:T/0 OR 103:C/0 OR 83:j/0 OR 131:5/0 OR 228:c/0 OR 207:N/0 OR 274:J/0 OR 24:A/0 OR 110:B/0 OR 116:b/0 OR 44:a/0 OR 130:O/0 OR 16:U/0 OR 11:O/0 OR 280:O/0 OR 116:O/0 OR 23:K/0 OR 17:H/0 OR 72:H/0 OR 432:Z/0 OR 30:Z/0 OR 132:O/0 OR 46:Q/0 OR 131:C/0 OR 207:c/0 OR 355:Q/0 OR 106:Q/0 OR 177:2/0 OR 191:2/0 OR 78:9/0 OR 3:9/0 OR 176:V/0 OR 131:W/0 OR 219:V/0 OR 249:R/0 OR 129:U/0 OR 365:O/0 OR 157:F/0 OR 209:F/0 OR 75:f/0 OR 62:f/0 OR 97:M/0 OR 280:L/0 OR 371:R/0 OR 430:Q/0 OR 211:O/0 OR 364:P/0 OR 233:K/0 OR 357:P/0 OR 37:Q/0 OR 34:U/0 OR 25:P/0 OR 18:J/0 OR 77:J/0 OR 20:L/0 OR 56:S/0 OR 244:S/0 OR 331:S/0 OR 141:A/0 OR 35:a/0 OR 3:J/0 OR 191:D/0 OR 228:D/0 OR 62:d/0 OR 133:d/0 OR 75:H/0 OR 21:N/0 OR 130:S/0 OR 688:N/0 OR 59:J/0 OR 24:H/0 OR 137:F/0 OR 136:F/0 OR 216:f/0 OR 82:f/0 OR 376:P/0 OR 219:P/0 OR 660:N/0 OR 197:W/0 OR 254:U/0 OR 280:R/0 OR 239:T/0 OR 263:S/0 OR 123:X/0 OR 281:I/0 OR 1:X/0 OR 402:N/0 OR 428:N/0 OR 6:N/0 OR 449:Z/0 OR 19:M/0 OR 270:L/0 OR 66:M/0 OR 180:P/0 OR 226:B/0 OR 57:b/0 OR 82:K/0 OR 64:A/0 OR 146:a/0 OR 193:O/0 OR 144:L/0 OR 181:O/0 OR 161:P/0 OR 298:P/0 OR 451:Z/0 OR 295:Z/0 OR 206:E/0 OR 75:e/0 OR 227:S/0 OR 16:O/0 OR 285:O/0 OR 160:U/0 OR 387:R/0 OR 39:O/0 OR 155:O/0 OR 315:O/0 OR 238:L/0 OR 8:K/0 OR 278:J/0 OR 326:M/0 OR 24:I/0 OR 530:N/0 OR 49:N/0 OR 97:I/0 OR 126:H/0 OR 338:J/0 OR 155:G/0 OR 243:A/0 OR 170:a/0 OR 135:g/0 OR 248:S/0 OR 391:R/0 OR 54:O/0 OR 23:O/0 OR 124:Z/0 OR 210:E/0 OR 20:E/0 OR 110:e/0 OR 120:e/0 OR 230:A/0 OR 59:a/0 OR 5:H/0 OR 148:1/0 OR 81:2/0 OR 127:9/0 OR 199:8/0 OR 164:Q/0 OR 95:U/0 OR 114:U/0 OR 46:N/0 OR 45:X/0 OR 56:B/0 OR 96:b/0 OR 25:D/0 OR 151:d/0 OR 282:R/0 OR 1:M/0 OR 188:U/0 OR 148:I/0 OR 79:P/0 OR 716:N/0 OR 269:K/0 OR 86:R/0 OR 101:1/0 OR 66:1/0 OR 163:8/0 OR 101:8/0 OR 210:J/0 OR 322:O/0 OR 118:U/0 OR 660:Z/0 OR 637:Z/0 OR 740:Z/0 OR 154:L/0 OR 231:U/0 OR 134:U/0 OR 333:K/0 OR 374:Q/0 OR 270:Q/0 OR 135:Q/0 OR 213:U/0 OR 53:J/0 OR 337:S/0 OR 186:1/0 OR 48:8/0 OR 243:L/0 OR 67:D/0 OR 170:d/0 OR 105:J/0 OR 190:O/0 OR 160:K/0 OR 303:K/0 OR 165:L/0 OR 166:J/0 OR 17:X/0 OR 342:S/0 OR 161:k/0 OR 109:6/0 OR 224:J/0 OR 50:Q/0 OR 134:J/0 OR 205:I/0 OR 74:I/0 OR 225:E/0 OR 49:e/0 OR 121:G/0 OR 225:g/0 OR 152:L/0 OR 363:R/0 OR 159:R/0 OR 323:K/0 OR 278:L/0 OR 326:J/0 OR 53:N/0 OR 141:D/0 OR 158:d/0 OR 254:I/0 OR 374:O/0 OR 250:O/0 OR 205:U/0 OR 28:1/0 OR 170:i/0 OR 25:4/0 OR 116:8/0 OR 376:N/0 OR 81:1/0 OR 95:l/0 OR 94:7/0 OR 208:8/0 OR 280:H/0 OR 125:K/0 OR 22:E/0 OR 33:E/0 OR 134:e/0 OR 148:e/0 OR 302:P/0 OR 79:U/0 OR 232:P/0 OR 343:P/0 OR 206:I/0 OR 261:R/0 OR 107:P/0 OR 255:L/0 OR 83:W/0 OR 154:J/0 OR 169:R/0 OR 20:R/0 OR 712:N/0 OR 61:M/0 OR 102:G/0 OR 80:g/0 OR 170:W/0 OR 181:J/0 OR 403:S/0 OR 236:L/0 OR 154:H/0 OR 364:P/0 OR 2:K/0 OR 212:O/0 OR 42:U/0 OR 240:J/0 OR 334:O/0 OR 164:O/0 OR 31:1/0 OR 209:8/0 OR 219:N/0 OR 353:S/0 OR 30:S/0 OR 204:D/0 OR 111:d/0 OR 808:N/0 OR 331:N/0 OR 232:U/0 OR 250:P/0 OR 179:D/0 OR 18:I/0 OR 45:d/0 OR 164:M/0 OR 21:H/0 OR 183:B/0 OR 148:b/0 OR 323:K/0 OR 317:O/0 OR 53:M/0 OR 7:M/0 OR 113:J/0 OR 34:C/0 OR 56:c/0 OR 345:H/0 OR 685:N/0 OR 51:S/0 OR 185:W/0 OR 33:F/0 OR 125:f/0 OR 56:I/0 OR 106:P/0 OR 210:T/0 OR 55:T/0 OR 149:H/0 OR 93:W/0 OR 355:S/0 OR 36:U/0 OR 146:O/0 OR 705:N/0 OR 214:T/0 OR 85:S/0 OR 309:I/0 OR 177:M/0 OR 380:N/0 OR 57:X/0 OR 34:V/0 OR 142:1/0 OR 19:8/0 OR 674:N/0 OR 19:K/0 OR 141:k/0 OR 150:6/0 OR 39:O/0 OR 120:k/0 OR 183:k/0 OR 178:6/0 OR 25:6/0 OR 311:Q/0 OR 147:Q/0 OR 52:L/0 OR 96:C/0 OR 41:C/0 OR 179:c/0 OR 49:c/0 OR 115:T/0 OR 284:S/0 OR 133:i/0 OR 83:2/0 OR 109:9/0 OR 197:4/0 OR 70:V/0 OR 33:J/0 OR 100:C/0 OR 69:c/0 OR 191:P/0 OR 99:V/0 OR 92:Q/0 OR 203:L/0 OR 13:J/0 OR 55:H/0 OR 155:2/0 OR 159:9/0 OR 236:G/0 OR 49:g/0 OR 71:N/0 OR 52:G/0 OR 138:g/0 OR 230:T/0 OR 40:T/0 OR 332:K/0 OR 168:U/0 OR 131:L/0 OR 128:D/0 OR 70:d/0 OR 161:J/0 OR 232:H/0 OR 168:A/0 OR 180:a/0 OR 34:O/0 OR 66:2/0 OR 204:9/0 OR 408:P/0 OR 317:L/0 OR 334:L/0 OR 244:N/0 OR 272:M/0 OR 334:N/0 OR 95:P/0 OR 156:I/0 OR 138:E/0 OR 20:e/0 OR 123:H/0 OR 85:M/0 OR 219:Q/0 OR 41:H/0 OR 389:Q/0 OR 288:Q/0 OR 53:1/0 OR 179:8/0 OR 258:Q/0 OR 252:Q/0 OR 416:Z/0 OR 125:Q/0 OR 259:L/0 OR 120:J/0 OR 175:I/0 OR 202:1/0 OR 65:l/0 OR 46:7/0 OR 67:8/0 OR 213:E/0 OR 45:E/0 OR 56:e/0 OR 232:e/0 OR 550:Z/0 OR 398:Q/0 OR 208:N/0 OR 94:H/0 OR 400:N/0 OR 334:L/0 OR 133:K/0 OR 86:U/0 OR 121:R/0 OR 192:R/0 OR 259:S/0 OR 305:L/0 OR 104:2/0 OR 161:9/0 OR 292:P/0 OR 369:P/0 OR 133:R/0 OR 418:S/0 OR 373:J/0 OR 125:O/0 OR 363:R/0 OR 157:L/0 OR 59:j/0 OR 74:5/0 OR 135:T/0 OR 70:M/0 OR 65:L/0 OR 193:H/0 OR 290:P/0 OR 331:P/0 OR 372:Q/0 OR 293:K/0 OR 175:h/0 OR 98:3/0 OR 117:R/0 OR 317:I/0 OR 214:C/0 OR 60:c/0 OR 9:T/0 OR 244:V/0 OR 196:V/0 OR 253:N/0 OR 270:R/0 OR 227:T/0 OR 40:T/0 OR 102:k/0 OR 76:6/0 OR 4:D/0 OR 149:I/0 OR 172:d/0 OR 97:D/0 OR 210:d/0 OR 109:T/0 OR 218:T/0 OR 282:Q/0 OR 3:2/0 OR 199:F/0 OR 18:f/0 OR 4:9/0 OR 375:Q/0 OR 42:A/0 OR 232:C/0 OR 64:c/0 OR 14:a/0 OR 165:P/0 OR 428:S/0 OR 722:Z/0 OR 123:F/0 OR 216:f/0 OR 123:G/0 OR 195:G/0 OR 1:g/0 OR 114:g/0 OR 179:i/0 OR 202:4/0 OR 118:V/0 OR 357:K/0 OR 55:I/0 OR 542:Z/0 OR 103:W/0 OR 94:Q/0 OR 109:U/0 OR 295:M/0 OR 295:L/0 OR 219:K/0 OR 270:M/0 OR 256:M/0 OR 226:U/0 OR 39:k/0 OR 167:6/0 OR 448:N/0 OR 401:S/0 OR 251:M/0 OR 38:M/0 OR 78:Q/0 OR 111:Q/0 OR 35:1/0 OR 61:1/0 OR 177:8/0 OR 122:8/0 OR 102:N/0 OR 240:S/0 OR 357:R/0 OR 126:V/0 OR 90:U/0 OR 59:I/0 OR 139:S/0 OR 269:S/0 OR 101:J/0 OR 9:j/0 OR 203:5/0 OR 327:M/0 OR 6:U/0 OR 116:P/0 OR 95:S/0 OR 210:O/0 OR 13:N/0 OR 4:X/0 OR 655:Z/0 OR 181:S/0 OR 280:Q/0 OR 49:G/0 OR 218:T/0 OR 94:g/0 OR 69:D/0 OR 109:D/0 OR 194:d/0 OR 124:d/0 OR 145:G/0 OR 65:g/0 OR 29:O/0 OR 90:B/0 OR 181:b/0 OR 137:N/0 OR 635:Z/0 OR 65:k/0 OR 155:6/0 OR 112:j/0 OR 128:l/0 OR 59:7/0 OR 57:5/0 OR 299:Q/0 OR 275:Q/0 OR 211:F/0 OR 171:F/0 OR 117:f/0 OR 4:f/0 OR 55:1/0 OR 55:8/0 OR 88:K/0 OR 153:U/0 OR 35:U/0 OR 211:P/0 OR 221:H/0 OR 5:L/0 OR 156:V/0 OR 204:V/0 OR 99:L/0 OR 45:U/0 OR 105:T/0 OR 17:C/0 OR 35:c/0 OR 248:I/0 OR 199:S/0 OR 295:R/0 OR 71:V/0 OR 118:S/0 OR 44:C/0 OR 120:c/0 OR 197:O/0 OR 115:Q/0 OR 111:H/0 OR 510:Z/0 OR 91:l/0 OR 81:7/0 OR 86:O/0 OR 124:E/0 OR 45:e/0 OR 145:F/0 OR 132:f/0 OR 90:S/0 OR 388:S/0 OR 577:N/0 OR 485:N/0 OR 62:N/0 OR 425:Q/0 OR 85:D/0 OR 72:d/0 OR 275:P/0 OR 110:B/0 OR 211:b/0 OR 370:N/0 OR 28:I/0 OR 341:R/0 OR 279:L/0 OR 82:V/0 OR 37:Q/0 OR 44:B/0 OR 197:b/0 OR 229:J/0 OR 120:U/0 OR 249:T/0 OR 233:T/0 OR 160:B/0 OR 82:b/0 OR 88:V/0 OR 199:P/0 OR 734:N/0 OR 82:E/0 OR 158:e/0 OR 153:A/0 OR 136:a/0 OR 59:J/0 OR 63:L/0 OR 11:Q/0 OR 7:S/0 OR 76:1/0 OR 14:V/0 OR 49:8/0 OR 7:P/0 OR 156:R/0 OR 548:N/0 OR 140:N/0 OR 124:R/0 OR 429:Q/0 OR 246:Q/0 OR 13:W/0 OR 79:H/0 OR 171:S/0 OR 158:1/0 OR 217:8/0 OR 519:N/0 OR 104:Q/0 OR 353:Z/0 OR 538:Z/0 OR 199:T/0 OR 86:V/0 OR 586:Z/0 OR 27:W/0 OR 103:O/0 OR 377:Q/0 OR 77:N/0 OR 328:N/0 OR 197:T/0 OR 318:N/0 OR 205:L/0 OR 267:P/0 OR 271:H/0 OR 20:H/0 OR 223:I/0 OR 37:D/0 OR 195:d/0 OR 315:Z/0 OR 158:V/0 OR 630:N/0 OR 140:G/0 OR 171:g/0 OR 210:I/0 OR 69:R/0 OR 323:I/0 OR 20:E/0 OR 74:E/0 OR 134:e/0 OR 53:e/0 OR 90:Q/0 OR 226:U/0 OR 222:E/0 OR 69:e/0 OR 121:D/0 OR 222:d/0 OR 217:E/0 OR 222:e/0 OR 267:Q/0 OR 359:Z/0 OR 87:k/0 OR 112:6/0 OR 58:N/0 OR 70:S/0 OR 280:K/0 OR 70:M/0 OR 349:R/0 OR 53:D/0 OR 12:d/0 OR 104:A/0 OR 62:a/0 OR 78:O/0 OR 213:J/0 OR 132:N/0 OR 128:H/0 OR 68:Q/0 OR 58:J/0 OR 72:J/0 OR 256:Q/0 OR 157:U/0 OR 90:H/0 OR 2:V/0 OR 297:M/0 OR 353:M/0 OR 195:Q/0 OR 374:Q/0 OR 351:H/0 OR 150:I/0 OR 673:N/0 OR 133:I/0 OR 112:U/0 OR 221:M/0 OR 306:L/0 OR 293:P/0 OR 10:Q/0 OR 189:S/0 OR 636:N/0 OR 426:Q/0 OR 594:N/0 OR 682:N/0 OR 181:B/0 OR 196:b/0 OR 53:G/0 OR 25:g/0 OR 108:g/0 OR 12:G/0 ) AND .CA' + +var nestedSyntax = '(( /0 AND (( :1 AND (28 OR 31 OR 35 OR 53 OR 55 OR 61 OR 66 OR 76 OR 81 OR 101 OR 142 OR 148 OR 158 OR 186 OR 202) ) OR ( :2 AND (3 OR 66 OR 81 OR 83 OR 104 OR 155 OR 177 OR 191) ) OR ( :3 AND (98 OR 101) ) OR ( :4 AND (25 OR 197 OR 202) ) OR ( :5 AND (57 OR 74 OR 90 OR 131 OR 203) ) OR ( :6 AND (25 OR 30 OR 76 OR 85 OR 92 OR 109 OR 112 OR 150 OR 155 OR 167 OR 178 OR 181) ) OR ( :7 AND (46 OR 59 OR 71 OR 81 OR 94 OR 112) ) OR ( :8 AND (19 OR 48 OR 49 OR 55 OR 67 OR 101 OR 116 OR 122 OR 163 OR 177 OR 179 OR 199 OR 208 OR 209 OR 217) ) OR ( :9 AND (3 OR 4 OR 78 OR 109 OR 127 OR 159 OR 161 OR 204) ) OR ( :O AND (11 OR 16 OR 23 OR 29 OR 34 OR 39 OR 54 OR 70 OR 76 OR 78 OR 86 OR 103 OR 116 OR 125 OR 130 OR 132 OR 146 OR 155 OR 164 OR 171 OR 181 OR 190 OR 193 OR 197 OR 210 OR 211 OR 212 OR 237 OR 250 OR 280 OR 285 OR 315 OR 317 OR 322 OR 327 OR 334 OR 339 OR 354 OR 365 OR 374) ) OR ( :H AND (5 OR 17 OR 20 OR 21 OR 24 OR 41 OR 49 OR 55 OR 72 OR 75 OR 79 OR 90 OR 94 OR 110 OR 111 OR 123 OR 126 OR 128 OR 143 OR 149 OR 154 OR 193 OR 221 OR 232 OR 271 OR 278 OR 280 OR 321 OR 329 OR 345 OR 351) ) OR ( :M AND (1 OR 6 OR 7 OR 19 OR 38 OR 39 OR 53 OR 61 OR 66 OR 70 OR 85 OR 97 OR 124 OR 133 OR 145 OR 162 OR 164 OR 177 OR 192 OR 196 OR 221 OR 251 OR 256 OR 267 OR 270 OR 272 OR 295 OR 297 OR 313 OR 326 OR 327 OR 328 OR 335 OR 353 OR 356) ) OR ( :N AND (6 OR 13 OR 21 OR 30 OR 44 OR 46 OR 49 OR 53 OR 58 OR 62 OR 71 OR 77 OR 102 OR 132 OR 136 OR 137 OR 140 OR 159 OR 207 OR 208 OR 219 OR 244 OR 253 OR 269 OR 274 OR 315 OR 318 OR 328 OR 331 OR 334 OR 370 OR 376 OR 380 OR 389 OR 400 OR 402 OR 428 OR 448 OR 485 OR 490 OR 519 OR 530 OR 548 OR 577 OR 594 OR 630 OR 636 OR 638 OR 660 OR 666 OR 669 OR 673 OR 674 OR 682 OR 685 OR 688 OR 705 OR 712 OR 716 OR 720 OR 734 OR 785 OR 808) ) OR ( :L AND (5 OR 8 OR 20 OR 40 OR 52 OR 63 OR 65 OR 70 OR 79 OR 99 OR 101 OR 108 OR 112 OR 131 OR 144 OR 152 OR 154 OR 157 OR 165 OR 197 OR 203 OR 205 OR 236 OR 238 OR 243 OR 255 OR 257 OR 259 OR 270 OR 278 OR 279 OR 280 OR 295 OR 305 OR 306 OR 317 OR 334) ) OR ( :C AND (17 OR 34 OR 41 OR 44 OR 96 OR 99 OR 100 OR 103 OR 104 OR 131 OR 148 OR 195 OR 214 OR 232) ) OR ( :B AND (44 OR 56 OR 90 OR 105 OR 110 OR 160 OR 181 OR 183 OR 225 OR 226) ) OR ( :b AND (30 OR 57 OR 82 OR 96 OR 116 OR 121 OR 148 OR 181 OR 196 OR 197 OR 211 OR 225) ) OR ( :c AND (35 OR 44 OR 49 OR 56 OR 60 OR 61 OR 64 OR 69 OR 117 OR 120 OR 155 OR 179 OR 207 OR 214 OR 228) ) OR ( :I AND (5 OR 18 OR 24 OR 27 OR 28 OR 44 OR 55 OR 56 OR 59 OR 74 OR 97 OR 133 OR 139 OR 148 OR 149 OR 150 OR 156 OR 175 OR 187 OR 205 OR 206 OR 210 OR 223 OR 248 OR 254 OR 281 OR 309 OR 317 OR 323) ) OR ( :T AND (9 OR 40 OR 53 OR 55 OR 105 OR 109 OR 115 OR 135 OR 141 OR 182 OR 197 OR 199 OR 210 OR 214 OR 218 OR 227 OR 230 OR 233 OR 239 OR 249 OR 261) ) OR ( :X AND (1 OR 4 OR 17 OR 43 OR 45 OR 57 OR 81 OR 123) ) OR ( :J AND (3 OR 13 OR 15 OR 18 OR 33 OR 52 OR 53 OR 58 OR 59 OR 72 OR 77 OR 86 OR 101 OR 105 OR 113 OR 120 OR 127 OR 134 OR 154 OR 161 OR 162 OR 166 OR 175 OR 181 OR 199 OR 204 OR 210 OR 213 OR 224 OR 229 OR 240 OR 249 OR 255 OR 274 OR 278 OR 302 OR 326 OR 338 OR 354 OR 373) ) OR ( :Q AND (10 OR 11 OR 37 OR 46 OR 50 OR 68 OR 77 OR 78 OR 90 OR 92 OR 94 OR 104 OR 106 OR 111 OR 113 OR 115 OR 125 OR 135 OR 136 OR 138 OR 140 OR 144 OR 147 OR 164 OR 195 OR 219 OR 246 OR 252 OR 256 OR 258 OR 267 OR 270 OR 275 OR 280 OR 282 OR 288 OR 299 OR 311 OR 355 OR 372 OR 374 OR 375 OR 377 OR 389 OR 398 OR 401 OR 404 OR 425 OR 426 OR 429 OR 430) ) OR ( :E AND (20 OR 22 OR 33 OR 45 OR 74 OR 82 OR 109 OR 124 OR 138 OR 206 OR 210 OR 213 OR 217 OR 222 OR 225) ) OR ( :e AND (20 OR 45 OR 48 OR 49 OR 53 OR 56 OR 69 OR 75 OR 110 OR 120 OR 134 OR 148 OR 158 OR 222 OR 232) ) OR ( :K AND (2 OR 8 OR 19 OR 23 OR 28 OR 29 OR 31 OR 66 OR 73 OR 82 OR 88 OR 113 OR 125 OR 133 OR 160 OR 219 OR 227 OR 233 OR 235 OR 269 OR 276 OR 278 OR 280 OR 293 OR 303 OR 323 OR 329 OR 332 OR 333 OR 346 OR 357) ) OR ( :V AND (2 OR 14 OR 34 OR 43 OR 52 OR 70 OR 71 OR 82 OR 86 OR 88 OR 99 OR 118 OR 126 OR 154 OR 156 OR 158 OR 176 OR 188 OR 196 OR 204 OR 219 OR 244) ) OR ( :A AND (24 OR 32 OR 42 OR 64 OR 85 OR 101 OR 104 OR 109 OR 141 OR 153 OR 166 OR 168 OR 221 OR 230 OR 243) ) OR ( :a AND (14 OR 17 OR 35 OR 44 OR 59 OR 62 OR 68 OR 120 OR 131 OR 136 OR 146 OR 170 OR 177 OR 180) ) OR ( :l AND (27 OR 59 OR 65 OR 91 OR 95 OR 128) ) OR ( :R AND (20 OR 34 OR 69 OR 86 OR 117 OR 121 OR 124 OR 133 OR 156 OR 159 OR 169 OR 192 OR 248 OR 249 OR 261 OR 270 OR 280 OR 282 OR 295 OR 339 OR 341 OR 345 OR 349 OR 355 OR 357 OR 358 OR 363 OR 364 OR 371 OR 383 OR 387 OR 391) ) OR ( :h AND (81 OR 175) ) OR ( :Z AND (30 OR 124 OR 295 OR 315 OR 353 OR 359 OR 416 OR 432 OR 449 OR 451 OR 510 OR 524 OR 538 OR 542 OR 550 OR 586 OR 635 OR 637 OR 655 OR 660 OR 722 OR 740) ) OR ( :D AND (4 OR 25 OR 37 OR 53 OR 67 OR 69 OR 85 OR 97 OR 109 OR 121 OR 128 OR 141 OR 179 OR 181 OR 191 OR 202 OR 204 OR 228) ) OR ( :d AND (12 OR 45 OR 62 OR 70 OR 72 OR 73 OR 111 OR 124 OR 130 OR 133 OR 151 OR 158 OR 170 OR 172 OR 194 OR 195 OR 210 OR 222) ) OR ( :U AND (6 OR 12 OR 16 OR 34 OR 35 OR 36 OR 42 OR 45 OR 48 OR 56 OR 79 OR 86 OR 90 OR 95 OR 109 OR 112 OR 114 OR 118 OR 120 OR 129 OR 134 OR 138 OR 153 OR 157 OR 160 OR 168 OR 188 OR 205 OR 213 OR 226 OR 231 OR 232 OR 254) ) OR ( :P AND (7 OR 25 OR 79 OR 95 OR 106 OR 107 OR 112 OR 116 OR 161 OR 165 OR 180 OR 191 OR 199 OR 211 OR 219 OR 232 OR 250 OR 267 OR 275 OR 290 OR 292 OR 293 OR 298 OR 302 OR 331 OR 343 OR 357 OR 364 OR 369 OR 376 OR 404 OR 408) ) OR ( :k AND (33 OR 39 OR 65 OR 69 OR 72 OR 87 OR 102 OR 120 OR 141 OR 161 OR 174 OR 183) ) OR ( :j AND (9 OR 59 OR 80 OR 83 OR 112) ) OR ( :S AND (7 OR 30 OR 51 OR 56 OR 70 OR 85 OR 90 OR 95 OR 118 OR 130 OR 139 OR 171 OR 181 OR 189 OR 194 OR 199 OR 227 OR 240 OR 244 OR 248 OR 252 OR 259 OR 263 OR 269 OR 284 OR 331 OR 337 OR 342 OR 353 OR 355 OR 388 OR 401 OR 403 OR 418 OR 428) ) OR ( :W AND (13 OR 27 OR 83 OR 93 OR 103 OR 131 OR 170 OR 185 OR 197) ) OR ( :F AND (33 OR 123 OR 136 OR 137 OR 145 OR 157 OR 171 OR 199 OR 209 OR 211) ) OR ( :f AND (4 OR 18 OR 62 OR 75 OR 82 OR 117 OR 125 OR 132 OR 216) ) OR ( :G AND (12 OR 49 OR 52 OR 53 OR 102 OR 121 OR 123 OR 140 OR 145 OR 155 OR 195 OR 236) ) OR ( :g AND (1 OR 25 OR 49 OR 65 OR 80 OR 94 OR 108 OR 114 OR 135 OR 138 OR 171 OR 225) ) OR ( :i AND (133 OR 170 OR 179) )) ) ) AND .CA' + +stage.loadFile('rcsb://3jco').then(function (o) { + o.addRepresentation('cartoon', { + colorScheme: 'uniform' + }) + + o.addRepresentation('spacefill', { + sele: flatSyntax, + name: 'flatSyntaxRes', + color: 'blue', + opacity: 0.5 + }) + + o.addRepresentation('spacefill', { + sele: nestedSyntax, + name: 'nestedSyntaxRes', + color: 'red', + opacity: 0.5 + }) + + stage.autoView() +}) diff --git a/examples/examples/scripts/selection/ring.js b/examples/examples/scripts/selection/ring.js new file mode 100644 index 000000000..d3eec6698 --- /dev/null +++ b/examples/examples/scripts/selection/ring.js @@ -0,0 +1,10 @@ + +stage.loadFile('data://4w93.mmtf').then(function (o) { + o.addRepresentation('licorice', { sele: '[3L9]' }) + + o.addRepresentation('spacefill', { + radius: 0.5, sele: '[3L9] and ring' + }) + + stage.autoView() +}) diff --git a/examples/examples/scripts/selection/spatialHash.js b/examples/examples/scripts/selection/spatialHash.js new file mode 100644 index 000000000..cb3535635 --- /dev/null +++ b/examples/examples/scripts/selection/spatialHash.js @@ -0,0 +1,38 @@ + +stage.loadFile('rcsb://3sn6.mmtf', { + defaultRepresentation: false +}).then(function (o) { + o.addRepresentation('cartoon', { quality: 'low' }) + stage.autoView() + + var radius = 8 + var spacefillRepr = o.addRepresentation('ball+stick', { sele: 'NONE' }) + + function getCenterArray () { + var position = new NGL.Vector3() + position.copy(stage.viewerControls.position) + return position.negate() + } + + var sphereBuffer = new NGL.SphereBuffer({ + position: new Float32Array(getCenterArray().toArray()), + color: new Float32Array([ 1, 0.5, 1 ]), + radius: new Float32Array([ radius ]) + }) + o.addBufferRepresentation(sphereBuffer, { opacity: 0.5 }) + + var prevSele = '' + var prevPos = new NGL.Vector3(Infinity, Infinity, Infinity) + stage.viewerControls.signals.changed.add(function () { + var pos = getCenterArray() + if (pos.distanceTo(prevPos) > 0.1) { + sphereBuffer.setAttributes({ 'position': pos.toArray() }) + prevPos = pos + var sele = o.structure.getAtomSetWithinPoint(pos, radius).toSeleString() + if (sele !== prevSele) { + spacefillRepr.setSelection(sele) + prevSele = sele + } + } + }) +}) diff --git a/examples/examples/scripts/selection/sstruc.js b/examples/examples/scripts/selection/sstruc.js new file mode 100644 index 000000000..543eaf735 --- /dev/null +++ b/examples/examples/scripts/selection/sstruc.js @@ -0,0 +1,9 @@ + +stage.loadFile('data://1crn.pdb').then(function (o) { + o.addRepresentation('backbone', { color: 'sstruc' }) + o.addRepresentation('rocket', { sele: 'helix', color: 'sstruc' }) + o.addRepresentation('cartoon', { sele: 'sheet', color: 'sstruc' }) + o.addRepresentation('tube', { sele: 'turn', color: 'sstruc' }) + + stage.autoView() +}) diff --git a/examples/examples/scripts/showcase/chlorellaVirus.js b/examples/examples/scripts/showcase/chlorellaVirus.js new file mode 100644 index 000000000..66928fe9a --- /dev/null +++ b/examples/examples/scripts/showcase/chlorellaVirus.js @@ -0,0 +1,14 @@ + +stage.loadFile('data://1M4X.cif').then(function (o) { + o.addRepresentation('surface', { + sele: 'polymer', + assembly: 'BU1', + surfaceType: 'sas', + probeRadius: 0.1, + scaleFactor: 0.05, + colorScheme: 'atomindex', + colorScale: 'PiYG', + useWorker: false + }) + stage.tasks.onZeroOnce(function () { stage.autoView() }) +}) diff --git a/examples/examples/scripts/showcase/electrostatic-apbs.js b/examples/examples/scripts/showcase/electrostatic-apbs.js new file mode 100644 index 000000000..bc81c1909 --- /dev/null +++ b/examples/examples/scripts/showcase/electrostatic-apbs.js @@ -0,0 +1,50 @@ + +stage.loadFile('data://1crn_apbs.pqr').then(function (o) { + o.addRepresentation('cartoon', { + colorScheme: 'partialCharge', + colorScale: 'rwb' + }) + o.addRepresentation('licorice', { + colorScheme: 'partialCharge', + colorScale: 'rwb' + }) + + o.autoView() +}) + +stage.loadFile('data://1crn_apbs_pot.dx.gz').then(function (o) { + o.addRepresentation('dot', { + thresholdType: 'value', + thresholdMin: -5, + thresholdMax: 5, + thresholdOut: true, + dotType: 'sphere', + radius: 'abs-value', + scale: 0.001, + visible: true, + colorScheme: 'value', + colorScale: 'rwb' + }) + + o.addRepresentation('surface', { + isolevelType: 'value', + isolevel: -0.4, + smooth: 1, + color: 'red', + opacity: 0.6, + side: 'back', + opaqueBack: false + }) + + o.addRepresentation('surface', { + isolevelType: 'value', + isolevel: 0.4, + smooth: 1, + color: 'blue', + opacity: 0.6, + side: 'front', + opaqueBack: false + }) + + stage.autoView() +}) diff --git a/examples/examples/scripts/showcase/ferredoxin.js b/examples/examples/scripts/showcase/ferredoxin.js new file mode 100644 index 000000000..f5bb81264 --- /dev/null +++ b/examples/examples/scripts/showcase/ferredoxin.js @@ -0,0 +1,48 @@ + +stage.loadFile('data://1blu.mmtf').then(function (o) { + // show protein backbone + o.addRepresentation('backbone', { + color: 'skyblue' + }) + + // show iron-sulfur clusters enlarged by a factor of 2 + o.addRepresentation('ball+stick', { + sele: 'SF4', + scale: 2, + color: 'element' + }) + + // show sidechains of cysteins "bond" to iron-sulfur clusters + o.addRepresentation('licorice', { + sele: 'CYS and sidechainAttached and not 57', + color: 'yellow' + }) + + // show `.SG` atoms of cysteins "bond" to iron-sulfur clusters + o.addRepresentation('spacefill', { + sele: 'CYS and .SG and not 57', + color: 'yellow', + radius: 0.3 + }) + + // use distance representation with labels switched off + // to indicate "bonds" to cysteine sidechains + o.addRepresentation('distance', { + atomPair: [ + [ '18:A.SG', '102:A.FE1' ], + [ '37:A.SG', '102:A.FE3' ], + [ '40:A.SG', '102:A.FE4' ], + [ '49:A.SG', '102:A.FE2' ], + + [ '8:A.SG', '101:A.FE3' ], + [ '11:A.SG', '101:A.FE4' ], + [ '14:A.SG', '101:A.FE2' ], + [ '53:A.SG', '101:A.FE1' ] + ], + scale: 0.5, + color: 'element', + labelVisible: false + }) + + stage.autoView() +}) diff --git a/examples/examples/scripts/showcase/ferritin.js b/examples/examples/scripts/showcase/ferritin.js new file mode 100644 index 000000000..ad098cb63 --- /dev/null +++ b/examples/examples/scripts/showcase/ferritin.js @@ -0,0 +1,37 @@ + +// 4Y08 ONE MINUTE IRON LOADED HUMAN H FERRITIN +// 4ZJK FIVE MINUTES IRON LOADED HUMAN H FERRITIN +// 4OYN Fifteen minutes iron loaded human H ferritin + +Promise.all([ + + stage.loadFile('data://4Y08.pdb', { + defaultAssembly: 'BU1' + }).then(function (o) { + o.addRepresentation('rope', { + color: 'lightgreen', radius: 'sstruc', scale: 4.0 + }) + o.addRepresentation('spacefill', { + sele: '_Fe', color: 'red', scale: 1.0, opacity: 1.0 + }) + }), + + stage.loadFile('data://4ZJK.pdb', { + defaultAssembly: 'BU1' + }).then(function (o) { + o.addRepresentation('spacefill', { + sele: '_Fe', color: 'orange', scale: 1.0, opacity: 1.0 + }) + }), + + stage.loadFile('data://4OYN.pdb', { + defaultAssembly: 'BU1' + }).then(function (o) { + o.addRepresentation('spacefill', { + sele: '_Fe', color: 'yellow', scale: 1.0, opacity: 1.0 + }) + }) + +]).then(function () { + stage.autoView() +}) diff --git a/examples/examples/scripts/showcase/gfp.js b/examples/examples/scripts/showcase/gfp.js new file mode 100644 index 000000000..30281d940 --- /dev/null +++ b/examples/examples/scripts/showcase/gfp.js @@ -0,0 +1,32 @@ + +stage.loadFile('data://1ema.cif').then(function (o) { + o.addRepresentation('cartoon', { + color: 'white', + smoothSheet: true, + opacity: 0.3, + depthWrite: false, + side: 'front', + quality: 'high' + }) + + o.addRepresentation('licorice', { + sele: '64-68', + scale: 3, + color: 'green' + }) + + o.addRepresentation('point', { + sele: '64-68', + opacity: 0.15, + color: 'green', + useTexture: true, + pointSize: 40, + edgeBleach: 1, + alphaTest: 0, + depthWrite: false + }) + + var pa = o.structure.getView(new NGL.Selection('.CA')).getPrincipalAxes() + stage.animationControls.rotate(pa.getRotationQuaternion(), 0) + stage.autoView() +}) diff --git a/examples/examples/scripts/showcase/hiv.js b/examples/examples/scripts/showcase/hiv.js new file mode 100644 index 000000000..cf236a82f --- /dev/null +++ b/examples/examples/scripts/showcase/hiv.js @@ -0,0 +1,104 @@ + +function addElement (el) { + Object.assign(el.style, { + position: 'absolute', + zIndex: 10 + }) + stage.viewer.container.appendChild(el) +} + +function createElement (name, properties, style) { + var el = document.createElement(name) + Object.assign(el, properties) + Object.assign(el.style, style) + return el +} + +stage.loadFile('rcsb://3j3q.mmtf').then(function (o) { + o.autoView() + + var point = o.addRepresentation('point') + + var surface = o.addRepresentation('surface', { + surfaceType: 'sas', + smooth: 2, + scaleFactor: 0.2, + colorScheme: 'chainindex', + opaqueBack: false + }) + + var cartoon = o.addRepresentation('cartoon', { + sele: ':f0 or :f1 or :f2 or :f3 or :f4 or :f5', + colorScheme: 'chainindex' + }) + + o.addRepresentation('ball+stick', { + sele: ':f0', + colorScheme: 'element' + }) + + o.addRepresentation('rocket', { + sele: ':f0', + colorScheme: 'chainindex' + }) + + var pointButton = createElement('input', { + type: 'button', + value: 'toggle points' + }, { top: '12px', left: '12px' }) + pointButton.onclick = function (e) { + point.toggleVisibility() + } + addElement(pointButton) + + var surfaceButton = createElement('input', { + type: 'button', + value: 'toggle surface' + }, { top: '36px', left: '12px' }) + surfaceButton.onclick = function (e) { + surface.toggleVisibility() + } + addElement(surfaceButton) + + var cartoonButton = createElement('input', { + type: 'button', + value: 'toggle cartoon' + }, { top: '60px', left: '12px' }) + cartoonButton.onclick = function (e) { + cartoon.toggleVisibility() + } + addElement(cartoonButton) + + var centerAllButton = createElement('input', { + type: 'button', + value: 'center all' + }, { top: '96px', left: '12px' }) + centerAllButton.onclick = function (e) { + stage.autoView() + } + addElement(centerAllButton) + + var centerSubunitButton = createElement('input', { + type: 'button', + value: 'center subunit' + }, { top: '120px', left: '12px' }) + centerSubunitButton.onclick = function (e) { + o.autoView(':f0 or :f1 or :f2 or :f3 or :f4 or :f5') + } + addElement(centerSubunitButton) + + addElement(createElement('span', { + innerText: 'surface transparency' + }, { top: '156px', left: '12px', color: 'lightgrey' })) + var opacityRange = createElement('input', { + type: 'range', + value: 0, + min: 0, + max: 100, + step: 1 + }, { top: '172px', left: '12px' }) + opacityRange.oninput = function (e) { + surface.setParameters({ opacity: 1 - (e.target.value / 100) }) + } + addElement(opacityRange) +}) diff --git a/examples/examples/scripts/showcase/norovirus.js b/examples/examples/scripts/showcase/norovirus.js new file mode 100644 index 000000000..c09f45e64 --- /dev/null +++ b/examples/examples/scripts/showcase/norovirus.js @@ -0,0 +1,33 @@ + +// Inside the virus capsid is the 65 base pair structure of a conserved +// retroviral RNA packaging element from the Moloney murine leukemia virus +// for size comparison. The capsid is composed of 60 identical protein and +// normally hosts a RNA genome of about 7.500 base pairs. + +stage.setParameters({ clipNear: 35 }) + +stage.loadFile('data://1IHM.pdb', { + defaultAssembly: 'BU1' +}).then(function (o) { + o.addRepresentation('rope', { + subdiv: 1, + radialSegments: 5, + quality: 'user', + colorScheme: 'chainindex', + radius: 1.0, + scale: 4.0 + }) + stage.autoView() +}) + +stage.loadFile('data://2L1F.pdb', { + firstModelOnly: true +}).then(function (o) { + o.addRepresentation('cartoon', { + color: 'white', aspectRatio: 2.5, scale: 2.0 + }) + o.addRepresentation('base', { + colorScheme: 'resname', radius: 0.7 + }) + stage.autoView() +}) diff --git a/examples/examples/scripts/showcase/qmean.js b/examples/examples/scripts/showcase/qmean.js new file mode 100644 index 000000000..c741c282d --- /dev/null +++ b/examples/examples/scripts/showcase/qmean.js @@ -0,0 +1,79 @@ + +function createElement (name, properties, style) { + var el = document.createElement(name) + Object.assign(el, properties) + Object.assign(el.style, style) + return el +} + +function createSelect (options, properties, style) { + var select = createElement('select', properties, style) + options.forEach(function (d) { + select.add(createElement('option', { + value: d[ 0 ], text: d[ 1 ] + })) + }) + return select +} + +function addElement (el) { + Object.assign(el.style, { + position: 'absolute', + zIndex: 10 + }) + stage.viewer.container.appendChild(el) +} + +Promise.all([ + + stage.loadFile('data://1crn.pdb'), + NGL.autoLoad('data://1crn_qmean_local_scores.txt', { + ext: 'csv', + delimiter: ' ', + comment: '#', + columnNames: true + }) + +]).then(function (ol) { + var protein = ol[ 0 ] + var qmean = ol[ 1 ].data + + var qmeanScheme = NGL.ColormakerRegistry.addScheme(function (params) { + this.domain = [ 0.5, 1 ] + this.scale = 'PuBu' + this.mode = 'rgb' + var scale = this.getScale() + this.atomColor = function (atom) { + var value = parseFloat(qmean[ atom.residueIndex ][ 12 ]) + return scale(value) + } + }) + + var cartoon = protein.addRepresentation('cartoon', { color: qmeanScheme }) + + var schemeSelect = createSelect( + [ + [ qmeanScheme, 'qmean' ], + [ 'sstruc', 'secondary structure' ] + ], + null, + { top: '1em', left: '1em' } + ) + schemeSelect.onchange = function (e) { + cartoon.setParameters({ colorScheme: e.target.value }) + } + + var centerButton = createElement( + 'button', + { innerText: 'Center' }, + { top: '3em', left: '1em' } + ) + centerButton.onclick = function (e) { + stage.autoView(1000) + } + + addElement(schemeSelect) + addElement(centerButton) + + stage.autoView() +}) diff --git a/examples/examples/scripts/showcase/rhodopsin.js b/examples/examples/scripts/showcase/rhodopsin.js new file mode 100644 index 000000000..bbc3eb092 --- /dev/null +++ b/examples/examples/scripts/showcase/rhodopsin.js @@ -0,0 +1,40 @@ + +stage.loadFile('data://3pqr.pdb').then(function (o) { + o.addRepresentation('cartoon', { + color: 'residueindex', aspectRatio: 4, scale: 0.5 + }) + o.addRepresentation('rope', { + color: 'residueindex', visible: false + }) + o.addRepresentation('ball+stick', { + sele: '296 or RET', scale: 3, aspectRatio: 1.5 + }) + o.addRepresentation('surface', { + sele: 'RET', + opacity: 0.4, + useWorker: false + }) + o.addRepresentation('licorice', { + sele: '( ( 135 or 223 ) and sidechainAttached ) or ( 347 )', + scale: 3, + aspectRatio: 1.5 + }) + o.addRepresentation('contact', { + sele: '135 or 223 or 347', + contactType: 'polar', + scale: 0.7 + }) + o.addRepresentation('label', { + sele: '( 135 or 223 or 347 or 296 ) and .CB', + color: 'white', + scale: 1.7 + }) + o.addRepresentation('label', { + sele: 'RET and .C19', + color: 'white', + scale: 1.7, + labelType: 'resname' + }) + + stage.autoView() +}) diff --git a/examples/examples/scripts/showcase/ribosome.js b/examples/examples/scripts/showcase/ribosome.js new file mode 100644 index 000000000..af3275489 --- /dev/null +++ b/examples/examples/scripts/showcase/ribosome.js @@ -0,0 +1,44 @@ + +stage.loadFile('data://4UJD.cif.gz').then(function (o) { + o.addRepresentation('cartoon', { + + color: 'rgb( 127, 191, 255 )', + sele: ':A2 or :A3 or :A4 or :AA or :AB or :AC or :AD or :AE or :AF or :AG or :AH or :AI or :AJ or :AK or :AL or :AM or :AN or :AO or :AP or :AQ or :AR or :AS or :AT or :AU or :AV or :AW or :AX or :AY or :AZ or :Aa or :Ab or :Ac or :Ad or :Ae or :Af or :Ag or :Ah or :Ai or :Aj or :Ak or :Al or :Am or :An or :Ao or :Ap or :Aq or :Ar or :As or :At or :Au', + name: '60S' + + }) + + o.addRepresentation('cartoon', { + + color: 'rgb( 255, 255, 127 )', + sele: ':C1 or :CA or :CB or :CC or :CD or :CE or :CF or :CG or :CH or :CI or :CJ or :CK or :CL or :CM or :CN or :CO or :CP or :CQ or :CR or :CS or :CT or :CU or :CV or :CW or :CX or :CY or :CZ or :Ca or :Cb or :Cc or :Cd or :Ce or :Cf or :Cg', + name: '40S' + + }) + + o.addRepresentation('spacefill', { + + color: 'rgb( 255, 127, 255 )', + sele: ':BC', + name: 'IRES' + + }) + + o.addRepresentation('spacefill', { + + color: 'rgb( 51, 255, 51 )', + sele: ':BA', + name: 'tRNA' + + }) + + o.addRepresentation('spacefill', { + + color: 'rgb( 255, 0, 0 )', + sele: ':BB', + name: 'EIF5B' + + }) + + o.autoView() +}) diff --git a/examples/examples/scripts/showcase/viruses.js b/examples/examples/scripts/showcase/viruses.js new file mode 100644 index 000000000..796f72d76 --- /dev/null +++ b/examples/examples/scripts/showcase/viruses.js @@ -0,0 +1,80 @@ + +function addElement (el) { + Object.assign(el.style, { + position: 'absolute', + zIndex: 10 + }) + stage.viewer.container.appendChild(el) +} + +function createElement (name, properties, style) { + var el = document.createElement(name) + Object.assign(el, properties) + Object.assign(el.style, style) + return el +} + +var pdbs = [ '1stm', '3nap', '1sid', '2ft1', '4cwu' ] +var colors = [ 'red', 'yellow', 'green', 'lightblue', 'violet' ] + +Promise.all(pdbs.map(function (id) { + return stage.loadFile('rcsb://' + id) +})).then(function (ol) { + ol.map(function (o, i) { + var s = o.structure + var bu1 = s.biomolDict.BU1 + o.setPosition(bu1.getCenter(s).negate()) + o.addRepresentation('surface', { + sele: 'polymer', + assembly: 'BU1', + color: colors[ i ], + scaleFactor: 0.10, + surfaceType: 'sas' + }) + o.addAnnotation(bu1.getCenter(s), o.name) + }) + + stage.tasks.onZeroOnce(function () { stage.autoView() }) + stage.setParameters({ clipNear: 50 }) + + addElement(createElement('span', { + innerText: 'near clip' + }, { top: '12px', left: '12px', color: 'lightgrey' })) + var clipRange = createElement('input', { + type: 'range', + value: 50, + min: 0, + max: 100, + step: 1 + }, { top: '28px', left: '12px' }) + clipRange.oninput = function (e) { + stage.setParameters({ clipNear: e.target.value }) + } + addElement(clipRange) + + function center () { + ol.map(function (o, i) { + var s = o.structure + var bu1 = s.biomolDict.BU1 + o.setPosition(bu1.getCenter(s).negate()) + }) + } + + var animateButton = createElement('input', { + type: 'button', + value: 'animate' + }, { top: '52px', left: '12px' }) + var pos = [ 1175, 875, 400, -200, -1000 ] + animateButton.onclick = function (e) { + center() + var ac = stage.animationControls + ol.map(function (o, i) { + var s = o.structure + var bu1 = s.biomolDict.BU1 + var p = bu1.getCenter(s) + p.x += pos[ i ] + ac.moveComponent(ol[ i ], p, 1500) + }) + } + addElement(animateButton) +}) diff --git a/examples/examples/scripts/test/1blu.js b/examples/examples/scripts/test/1blu.js new file mode 100644 index 000000000..a7a76e1f1 --- /dev/null +++ b/examples/examples/scripts/test/1blu.js @@ -0,0 +1,15 @@ + +stage.loadFile('data://1blu.pdb').then(function (o) { + o.addRepresentation('cartoon', { sele: '*' }) + o.addRepresentation('backbone', { + sele: '*', + scale: 1.0, + aspectRatio: 1.5, + color: 'lightgreen' + }) + o.addRepresentation('licorice', { sele: '*', scale: 1.0 }) + + var center = o.getCenter('101') + var zoom = o.getZoom('101') + stage.animationControls.zoomMove(center, zoom, 0) +}) diff --git a/examples/examples/scripts/test/2buk.js b/examples/examples/scripts/test/2buk.js new file mode 100644 index 000000000..c2c4d2229 --- /dev/null +++ b/examples/examples/scripts/test/2buk.js @@ -0,0 +1,8 @@ + +stage.loadFile('data://2buk.pdb').then(function (o) { + o.addRepresentation('backbone', { + lineOnly: true, + assembly: 'UNITCELL' + }) + stage.autoView() +}) diff --git a/examples/examples/scripts/test/alignment.js b/examples/examples/scripts/test/alignment.js new file mode 100644 index 000000000..a640de702 --- /dev/null +++ b/examples/examples/scripts/test/alignment.js @@ -0,0 +1,26 @@ + +Promise.all([ + + stage.loadFile('data://3dqb.pdb', { + defaultAssembly: 'AU' + }).then(function (o) { + o.addRepresentation('cartoon', { color: 'lightgreen' }) + o.addRepresentation('ball+stick', { sele: 'hetero', color: 'lightgreen' }) + o.autoView() + return o + }), + + stage.loadFile('data://3sn6.pdb').then(function (o) { + o.addRepresentation('cartoon', { color: 'tomato' }) + o.addRepresentation('ball+stick', { sele: 'hetero', color: 'tomato' }) + o.autoView() + return o + }) + +]).then(function (ol) { + var s1 = ol[ 0 ].structure + var s2 = ol[ 1 ].structure + NGL.superpose(s1, s2, true) + ol[ 0 ].updateRepresentations({ position: true }) + ol[ 0 ].autoView() +}) diff --git a/examples/examples/scripts/test/alignment2.js b/examples/examples/scripts/test/alignment2.js new file mode 100644 index 000000000..ab797360f --- /dev/null +++ b/examples/examples/scripts/test/alignment2.js @@ -0,0 +1,22 @@ + +Promise.all([ + + stage.loadFile('data://1gzm.pdb').then(function (o) { + o.addRepresentation('cartoon', { color: 'lightgreen' }) + o.autoView() + return o + }), + + stage.loadFile('data://1u19.pdb').then(function (o) { + o.addRepresentation('cartoon', { color: 'tomato' }) + o.autoView() + return o + }) + +]).then(function (ol) { + var s1 = ol[ 0 ].structure + var s2 = ol[ 1 ].structure + NGL.superpose(s1, s2, true, ':A', ':A') + ol[ 0 ].updateRepresentations({ position: true }) + ol[ 0 ].autoView() +}) diff --git a/examples/examples/scripts/test/backboneTypeChange.js b/examples/examples/scripts/test/backboneTypeChange.js new file mode 100644 index 000000000..592341ff3 --- /dev/null +++ b/examples/examples/scripts/test/backboneTypeChange.js @@ -0,0 +1,8 @@ + +// test case for inter-chain backboneType changes + +stage.loadFile('data://4V60_A.pdb').then(function (o) { + o.addRepresentation('cartoon') + o.addRepresentation('licorice') + o.autoView() +}) diff --git a/examples/examples/scripts/test/concat.js b/examples/examples/scripts/test/concat.js new file mode 100644 index 000000000..91217db74 --- /dev/null +++ b/examples/examples/scripts/test/concat.js @@ -0,0 +1,28 @@ + +Promise.all([ + stage.loadFile('data://2vts-protein.pdb'), + stage.loadFile('data://2vts-docking.sdf') +]).then(function (ol) { + var cs = NGL.concatStructures( + 'concat', + ol[ 0 ].structure.getView(new NGL.Selection('not ligand')), + ol[ 1 ].structure.getView(new NGL.Selection('')) + ) + var comp = stage.addComponentFromObject(cs) + comp.addRepresentation('cartoon') + comp.addRepresentation('contact', { + masterModelIndex: 0, + weakHydrogenBond: true, + maxHbondDonPlaneAngle: 35, + sele: '/0 or /2' + }) + comp.addRepresentation('licorice', { + sele: 'ligand and /2', + multipleBond: 'offset' + }) + comp.addRepresentation('line', { + sele: '/0' + }) + comp.autoView('ligand') + stage.setFocus(95) +}) diff --git a/examples/examples/scripts/test/dashedCylinders.js b/examples/examples/scripts/test/dashedCylinders.js new file mode 100644 index 000000000..64ae3c8e4 --- /dev/null +++ b/examples/examples/scripts/test/dashedCylinders.js @@ -0,0 +1,28 @@ + +stage.loadFile('rcsb://1atp').then(function (o) { + o.addRepresentation('cartoon') + o.addRepresentation('licorice') + + var center = o.getCenter('355:E.O1G') + var zoom = o.getZoom('atp') + stage.animationControls.zoomMove(center, zoom, 0) + + var pos1 = [ 17.549999237060547, 8.53600025177002, -0.5149999856948853 ] + + var pos2 = [ + [ 19.740999221801758, 6.551000118255615, -0.546999990940094 ], + [ 19.969999313354492, 5.958000183105469, -1.8380000591278076 ], + [ 18.88599967956543, 6.414999961853027, -2.821000099182129 ], + [ 14.675999641418457, 8.154000282287598, -3.7300000190734863 ], + [ 13.555000305175781, 6.9029998779296875, -0.13099999725818634 ] + ] + + var shape = new NGL.Shape('shape', { dashedCylinder: true, radialSegments: 60 }) + + for (var i = 0; i < pos2.length; i++) { + shape.addCylinder(pos1, pos2[i], [ 1, 1, 0.4 ], 0.05, 'My test ' + i) + } + var shapeComp = stage.addComponentFromObject(shape) + shapeComp.addRepresentation('buffer') + shapeComp.autoView() +}) diff --git a/examples/examples/scripts/test/explode.js b/examples/examples/scripts/test/explode.js new file mode 100644 index 000000000..b2be0062a --- /dev/null +++ b/examples/examples/scripts/test/explode.js @@ -0,0 +1,56 @@ + +function addElement (el) { + Object.assign(el.style, { + position: 'absolute', + zIndex: 10 + }) + stage.viewer.container.appendChild(el) +} + +function createElement (name, properties, style) { + var el = document.createElement(name) + Object.assign(el, properties) + Object.assign(el.style, style) + return el +} + +stage.loadFile('data://3SN6.cif').then(function (o) { + var s = o.structure + var c = s.atomCenter() + var chainComps = [] + + s.eachChain(function (cp) { + if (!cp.entity.isPolymer()) return + + var sele = ':' + cp.chainname + var sc = s.getView(new NGL.Selection(sele)) + var oc = stage.addComponentFromObject(sc, { name: o.name + sele }) + oc.addRepresentation('cartoon') + chainComps.push(oc) + + var cc = sc.atomCenter() + cc.sub(c).normalize().multiplyScalar(30) + oc.setPosition(cc) + }) + + stage.autoView() + + addElement(createElement('span', { + innerText: 'explode' + }, { top: '12px', left: '12px', color: 'lightgrey' })) + var explodeRange = createElement('input', { + type: 'range', + value: 30, + min: 1, + max: 100, + step: 1 + }, { top: '28px', left: '12px' }) + explodeRange.oninput = function (e) { + chainComps.forEach(function (oc) { + var cc = oc.structure.atomCenter() + cc.sub(c).normalize().multiplyScalar(e.target.value) + oc.setPosition(cc) + }) + } + addElement(explodeRange) +}) diff --git a/examples/examples/scripts/test/helixorient_issue-7.js b/examples/examples/scripts/test/helixorient_issue-7.js new file mode 100644 index 000000000..6b831c74b --- /dev/null +++ b/examples/examples/scripts/test/helixorient_issue-7.js @@ -0,0 +1,12 @@ + +stage.loadFile('data://4YVS.cif', { + defaultAssembly: 'AU', + sele: '86-100:H' +}).then(function (o) { + o.addRepresentation('helixorient') + o.addRepresentation('rope', { + opacity: 0.4, side: 'front', smooth: 0 + }) + o.addRepresentation('licorice', { sele: 'backbone' }) + stage.autoView() +}) diff --git a/examples/examples/scripts/test/impostor.js b/examples/examples/scripts/test/impostor.js new file mode 100644 index 000000000..77bd0cdbc --- /dev/null +++ b/examples/examples/scripts/test/impostor.js @@ -0,0 +1,6 @@ + +stage.loadFile('data://1crn.pdb').then(function (o) { + o.addRepresentation('ball+stick', { sele: '16', disableImpostor: true }) + o.addRepresentation('ball+stick', { sele: 'not 16' }) + o.autoView('16') +}) diff --git a/examples/examples/scripts/test/inter-bonds.js b/examples/examples/scripts/test/inter-bonds.js new file mode 100644 index 000000000..c097be9e5 --- /dev/null +++ b/examples/examples/scripts/test/inter-bonds.js @@ -0,0 +1,5 @@ + +stage.loadFile('data://inter-bonds.pdb').then(function (o) { + o.addRepresentation('licorice') + o.autoView() +}) diff --git a/examples/examples/scripts/test/map-shift.js b/examples/examples/scripts/test/map-shift.js new file mode 100644 index 000000000..e8503d917 --- /dev/null +++ b/examples/examples/scripts/test/map-shift.js @@ -0,0 +1,35 @@ + +Promise.all([ + + stage.loadFile('data://JMJD2DA-x336_event2.ccp4.gz'), + stage.loadFile('data://JMJD2DA-x336_event2.pdb') + +]).then(function (ol) { + var map = ol[ 0 ] + var struc = ol[ 1 ] + + struc.autoView('LIG') + + var surfRepr = map.addRepresentation('surface', { + boxSize: 10, + useWorker: false, + wrap: true, + color: 'skyblue', + contour: true + }) + + struc.addRepresentation('cartoon') + struc.addRepresentation('ball+stick', { sele: 'hetero' }) + + stage.setFocus(95) + + // remove default scroll mouse action + stage.mouseControls.remove('scroll') + + // change isolevel on mouse scroll + stage.mouseControls.add('scroll', function (stage, delta) { + var d = Math.sign(delta) / 5 + var l = surfRepr.getParameters().isolevel + surfRepr.setParameters({ isolevel: l + d }) + }) +}) diff --git a/examples/examples/scripts/test/molsurf-object.js b/examples/examples/scripts/test/molsurf-object.js new file mode 100644 index 000000000..e84904ee2 --- /dev/null +++ b/examples/examples/scripts/test/molsurf-object.js @@ -0,0 +1,12 @@ + +NGL.autoLoad('data://1crn.pdb').then(function (structure) { + var molsurf = new NGL.MolecularSurface(structure) + var surf = molsurf.getSurface({ + type: 'av', + probeRadius: 1.4, + name: 'molsurf' + }) + var o = stage.addComponentFromObject(surf) + o.addRepresentation('surface') + o.autoView() +}) diff --git a/examples/examples/scripts/test/nci.js b/examples/examples/scripts/test/nci.js new file mode 100644 index 000000000..3b7ecc63d --- /dev/null +++ b/examples/examples/scripts/test/nci.js @@ -0,0 +1,473 @@ + +function addElement (el) { + Object.assign(el.style, { + position: 'absolute', + zIndex: 10 + }) + stage.viewer.container.appendChild(el) +} + +function createElement (name, properties, style) { + var el = document.createElement(name) + Object.assign(el, properties) + Object.assign(el.style, style) + return el +} + +function createSelect (options, properties, style) { + var select = createElement('select', properties, style) + options.forEach(function (d) { + select.add(createElement('option', { + value: d[ 0 ], text: d[ 1 ] + })) + }) + return select +} + +function createFileButton (label, properties, style) { + var input = createElement('input', Object.assign({ + type: 'file' + }, properties), { display: 'none' }) + addElement(input) + var button = createElement('input', { + value: label, + type: 'button', + onclick: function () { input.click() } + }, style) + return button +} + +function loadStructure (input) { + stage.removeAllComponents() + return stage.loadFile(input).then(function (o) { + o.addRepresentation('ribbon') + o.addRepresentation('licorice', { + multipleBond: 'symmetric' + }) + o.addRepresentation('contact', { + weakHydrogenBond: true, + waterHydrogenBond: true, + backboneHydrogenBond: true, + hydrophobic: true, + saltBridge: true + }) + stage.setFocus(0) + stage.autoView() + }) +} + +function loadExample (input) { + stage.removeAllComponents() + return stage.loadFile('rcsb://' + input.pdbid).then(function (o) { + var sele = '(' + input.sele1 + ') or (' + input.sele2 + ')' + var groupSele = o.structure.getAtomSetWithinGroup(new NGL.Selection(sele)).toSeleString() + o.autoView(sele) + o.addRepresentation('ribbon', { + visible: false + }) + o.addRepresentation('ball+stick', { + multipleBond: 'symmetric', + sele: sele + }) + o.addRepresentation('licorice', { + radiusScale: 0.5, + multipleBond: 'symmetric', + sele: groupSele + }) + o.addRepresentation('line', { + multipleBond: 'symmetric', + linewidth: 3 + }) + o.addRepresentation('contact', { + weakHydrogenBond: true, + waterHydrogenBond: true, + backboneHydrogenBond: true, + hydrophobic: true, + saltBridge: true + }) + stage.setFocus(95) + }) +} + +// create tooltip element and add to document body +var tooltip = document.createElement('div') +Object.assign(tooltip.style, { + display: 'none', + position: 'fixed', + zIndex: 10, + pointerEvents: 'none', + backgroundColor: 'rgba( 0, 0, 0, 0.6 )', + color: 'lightgrey', + padding: '8px', + fontFamily: 'sans-serif' +}) +document.body.appendChild(tooltip) + +// remove default hoverPick mouse action +stage.mouseControls.remove('hoverPick') + +// listen to `hovered` signal to move tooltip around and change its text +stage.signals.hovered.add(function (pickingProxy) { + if (pickingProxy) { + if (pickingProxy.atom || pickingProxy.bond) { + var atom = pickingProxy.atom || pickingProxy.closestBondAtom + var vm = atom.structure.data['@valenceModel'] + if (vm && vm.idealValence) { + tooltip.innerHTML = `${pickingProxy.getLabel()}
+
+ Atom: ${atom.qualifiedName()}
+ ideal valence: ${vm.idealValence[atom.index]}
+ ideal geometry: ${vm.idealGeometry[atom.index]}
+ implicit charge: ${vm.implicitCharge[atom.index]}
+ formal charge: ${atom.formalCharge === null ? '?' : atom.formalCharge}
+ aromatic: ${atom.aromatic ? 'true' : 'false'}
+ ` + } else if (vm && vm.charge) { + tooltip.innerHTML = `${pickingProxy.getLabel()}
+
+ Atom: ${atom.qualifiedName()}
+ vm charge: ${vm.charge[atom.index]}
+ vm implicitH: ${vm.implicitH[atom.index]}
+ vm totalH: ${vm.totalH[atom.index]}
+ vm geom: ${vm.idealGeometry[atom.index]}
+ formal charge: ${atom.formalCharge === null ? '?' : atom.formalCharge}
+ aromatic: ${atom.aromatic ? 'true' : 'false'}
+ ` + } else { + tooltip.innerHTML = `${pickingProxy.getLabel()}` + } + } else { + tooltip.innerHTML = `${pickingProxy.getLabel()}` + } + var mp = pickingProxy.mouse.position + tooltip.style.bottom = window.innerHeight - mp.y + 3 + 'px' + tooltip.style.left = mp.x + 3 + 'px' + tooltip.style.display = 'block' + } else { + tooltip.style.display = 'none' + } +}) + +stage.signals.clicked.add(function (pickingProxy) { + if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) { + console.log(pickingProxy.atom || pickingProxy.closestBondAtom) + } +}) + +function setTestOptions () { + testSelect.innerHTML = '' + testSelect.add(createElement('option', { value: '', text: '' })) + nciTests.forEach(function (d, i) { + testSelect.add(createElement('option', { + value: i, text: '[' + d.type + '] ' + d.info + })) + }) +} + +var loadStructureButton = createFileButton('load structure', { + accept: '.pdb,.cif,.ent,.gz,.mol2', + onchange: function (e) { + if (e.target.files[ 0 ]) { + testSelect.value = '' + testInfo.innerText = '' + loadStructure(e.target.files[ 0 ]) + } + } +}, { top: '12px', left: '12px' }) +addElement(loadStructureButton) + +var loadPdbidText = createElement('span', { + innerText: 'load pdb id' +}, { top: '50px', left: '12px', color: 'grey' }) +addElement(loadPdbidText) + +var loadPdbidInput = createElement('input', { + type: 'text', + title: 'press enter to load pdbid', + onkeypress: function (e) { + if (e.keyCode === 13) { + e.preventDefault() + testSelect.value = '' + testInfo.innerText = '' + loadStructure('rcsb://' + e.target.value) + } + } +}, { top: '70px', left: '12px', width: '120px' }) +addElement(loadPdbidInput) + +var testText = createElement('span', { + innerText: 'load example' +}, { top: '110px', left: '12px', color: 'grey' }) +addElement(testText) + +var testSelect = createSelect([], { + onchange: function (e) { + loadPdbidInput.value = '' + var input = nciTests[ e.target.value ] + testInfo.innerHTML = '' + + input.type + '
' + + input.info + '
' + + (input.desc ? (input.desc + '
') : '') + + input.sele1 + '
' + + input.sele2 + '' + loadExample(input) + } +}, { top: '130px', left: '12px', width: '130px' }) +addElement(testSelect) + +var testInfo = createElement('div', { + innerText: '' +}, { top: '150px', left: '12px', color: 'grey' }) +addElement(testInfo) + +var nciTests = JSON.parse(` +[ + { + "pdbid": "5pbf", + "sele1": "[8HJ] and 2003:A.N1", + "sele2": "ASN and 1944:A.OD1", + "type": "hydrogen-bond", + "info": "standard bromodomain fragment, acceptor" + }, + { + "pdbid": "5pbf", + "sele1": "[8HJ] and 2003:A.O1", + "sele2": "(ASN and 1944:A.ND2) or (HOH and 2115:A.O)", + "type": "hydrogen-bond", + "info": "standard bromodomain fragment, donor 1" + }, + { + "pdbid": "5pbf", + "sele1": "[8HJ] and 2003:A.O2", + "sele2": "HOH and 2217:A.O", + "type": "hydrogen-bond", + "info": "standard bromodomain fragment, donor 2" + }, + { + "pdbid": "4x0x", + "sele1": "CYS and 45:B.SG", + "sele2": "(LEU and 39:B.O) or (ARG and 116:B and (.NH1 or .NH2))", + "type": "hydrogen-bond", + "info": "cystein donor/acceptor" + }, + { + "pdbid": "2vts", + "sele1": "LZC and 1299:A.C21", + "sele2": "GLU and 81:A.O", + "type": "weak-hydrogen-bond", + "info": "common in kinase ligands" + }, + { + "pdbid": "1ac4", + "sele1": "TMT and 296:A.C5", + "sele2": "ASP and 235:A.OD2", + "type": "weak-hydrogen-bond", + "info": "ligand C donor, aspartate oxygen acceptor" + }, + { + "pdbid": "1gqu", + "sele1": "DA and 1:A.C8", + "sele2": "DT and 12:B.O2", + "type": "weak-hydrogen-bond", + "info": "hoogsteen base pairing" + }, + { + "pdbid": "1crn", + "sele1": "THR and 2:A.CA", + "sele2": "ILE and 33:A.O", + "type": "weak-hydrogen-bond", + "info": "beta sheet backbone contact" + }, + { + "pdbid": "191d", + "sele1": "DC and 6:B.C4'", + "sele2": "DC and 11:C.O4'", + "type": "weak-hydrogen-bond", + "info": "DNA backbone contact" + }, + { + "pdbid": "3sn6", + "sele1": "ARG and 131:R and (.NE or .NH1 or .NH2)", + "sele2": "TYR and 391:A and aromaticRing", + "type": "cation-pi", + "info": "receptor G protein interface" + }, + { + "pdbid": "4cwd", + "sele1": "[449] and 1385:A.NAK", + "sele2": "TYR and 177:A and aromaticRing", + "type": "cation-pi", + "info": "ligand quaternary amine, tyrosine ring" + }, + { + "pdbid": "3apv", + "sele1": "TP0 and 190:A.N1", + "sele2": "TYR and 37:A and aromaticRing", + "type": "cation-pi", + "info": "ligand tertiary amine, tyrosin ring" + }, + { + "pdbid": "3e5c", + "sele1": "SAM and 216:A.SD", + "sele2": "G and 36:A and (.C4 or .C5 or .N7 or .C8 or .N9)", + "type": "cation-pi", + "info": "ligand sulfonium, guanosine ring" + }, + { + "pdbid": "3eqa", + "sele1": "LYS and 132:A.NZ", + "sele2": "((TRP and 144:A) or (TYR and (140:A or 74:A)) and aromaticRing", + "type": "cation-pi", + "info": "lysine, tryptophan and tyrosine rings" + }, + { + "pdbid": "1g54", + "sele1": "FFB and 555:A and (.C15 or .C16 or .C17 or .C18 or .C19 or .C20)", + "sele2": "PHE and 131:A and aromaticRing", + "type": "pi-stacking", + "info": "ligand protein, t-shaped" + }, + { + "pdbid": "4x21", + "sele1": "[3WH] and 501:A.I17", + "sele2": "MET and 146:A.SD", + "type": "halogen-bond", + "info": "ligand iodine, methionine sulfur" + }, + { + "pdbid": "4lau", + "sele1": "W8X and 402:A.BR7", + "sele2": "THR and 113:A.OG1", + "type": "halogen-bond", + "info": "ligand bromine, threonine oxygen" + }, + { + "pdbid": "2vts", + "sele1": "ARG and 274:A and (.NH1 or .CZ or .NH2)", + "sele2": "GLU and 172:A and (.OE1 or .CD or .OE2)", + "type": "salt-bridge", + "info": "between ARG and GLU, hbonds hidden" + }, + { + "pdbid": "3apv", + "sele1": "TP0 and 190:A.N1", + "sele2": "ACY and 191:A and (.C or .OXT or .O)", + "type": "salt-bridge", + "info": "ligand tertiary amine, ligand carboxyl group" + }, + { + "pdbid": "1tbz", + "sele1": "[00Q] and 343:H and (.NH1 or .NH2 or .NEY)", + "sele2": "ASP and 189:H and (.OD1 or .OD2)", + "type": "salt-bridge", + "info": "ligand guainidine group, aspartate sidechain" + }, + { + "pdbid": "3nkk", + "sele1": "JLZ and 1:A and (.N12 or .N14)", + "sele2": "ASP and 189:A and (.OD1 or .OD2)", + "type": "salt-bridge", + "info": "ligand acetamidine group, aspartate sidechain" + }, + { + "pdbid": "3cup", + "sele1": "EPE and 302:A and (.O1S or .O2S or .O3S)", + "sele2": "ARG and 389:B and (.NE or .NH1 or .NH2)", + "type": "salt-bridge", + "info": "ligand sulfonic-acid group, arginine sidechain" + }, + { + "pdbid": "1vkj", + "sele1": "A3P and 602:A and (.O4P or .O5P or .O6P or .O5')", + "sele2": "LYS and 274:A.NZ", + "type": "salt-bridge", + "info": "ligand phospate group, lysine sidechain" + }, + { + "pdbid": "2bxh", + "sele1": "IOS and 1001:A and (.O1 or .O2 or .O3 or .O4)", + "sele2": "ARG and 410:A and (.NE or .NH1 or .NH2)", + "type": "salt-bridge", + "info": "ligand sulfate group, arginine sidechain" + }, + { + "pdbid": "1d66", + "sele1": "(DC and 13:D and (.OP1 or .OP2 or .O5')) or (DT and 12:D.O3')", + "sele2": "ARG and 46:B and (.NE or .NH1 or .NH2)", + "type": "salt-bridge", + "info": "DNA phospate group, arginine sidechain" + }, + { + "pdbid": "1ac8", + "sele1": "TMZ and 296:A.N3", + "sele2": "ASP and 235:A and (.OD1 or .OD2)", + "type": "salt-bridge", + "info": "ligand tertiary amine & weak hbonds, aspartate sidechain" + }, + { + "pdbid": "1blu", + "sele1": "SF4 and 102:A.FE2", + "sele2": "CYS and 49:A.SG", + "type": "metal-coordination", + "info": "cysteine to iron-sulfur cluster" + }, + { + "pdbid": "5vpw", + "sele1": "ICS and 602:A.MO1", + "sele2": "(HIS and 482:A.ND1) or (HCA and 601:A and (.O7 or .O6))", + "type": "metal-coordination", + "info": "molybdenum coordinated by histidine and ligand oxygens" + }, + { + "pdbid": "5k5h", + "sele1": "[ZN] and 502:A.ZN", + "sele2": "(CYS and 381:A.SG) or (CYS and 384:A.SG) or (HIS and 397:A.NE2) or (HIS and 401:A.NE2)", + "type": "metal-coordination", + "info": "zink coordinated by histidine and cysteine" + }, + { + "pdbid": "1n5w", + "sele1": "CUM and 3921:B.MO", + "sele2": "MCN and 3920:B and (.S7' or .S8')", + "type": "metal-coordination", + "info": "molybdenum coordinated by ligand sulfurs" + }, + { + "pdbid": "1n5w", + "sele1": "CUM and 3921:B.CU", + "sele2": "(CYS and 388:B.SG) or (HOH and 4334:B.O)", + "type": "metal-coordination", + "info": "copper coordinated by water and cysteine sidechain" + }, + { + "pdbid": "3hdi", + "sele1": "[CO] and 500:A.CO", + "sele2": "(GLU and 126:A and (.OE1 or .OE2)) or (HIS and 46:A.NE2) or (HIS and 50:A.NE2) or (ALA and 14:C.O)", + "type": "metal-coordination", + "info": "copper coordinated by backbone carbonyl, histidine and glutamate" + }, + { + "pdbid": "1en7", + "sele1": "[CA] and 403:A.CA", + "sele2": "(HOH and 447:A.O) or (HOH and 450:A.O) or (ASN and 62:A.OD2) or (ASP and 40:A.OD1)", + "type": "metal-coordination", + "info": "calcium coordinated by water, aspartate and asparagine" + }, + { + "pdbid": "5ph0", + "sele1": "[NI] and 402:A.NI", + "sele2": "(HOH and 598:A.O) or (HIS and 192:A.NE2) or (HIS and 280:A.NE2) or (GLU and 194:A.OE1) or (OGA and 404:A and (.O2' or .O1))", + "type": "metal-coordination", + "info": "nickel coordinated by ligand, water, glutamate and histidine" + }, + { + "pdbid": "1rla", + "sele1": "[MN] and 500:A.MN", + "sele2": "(HOH and 502:A.O) or (HIS and 101:A.ND1) or (ASP and (124:A or 128:A or 232:A) and .OD2)", + "type": "metal-coordination", + "info": "manganase coordinated by water, aspartate and histidine" + } +] +`) + +setTestOptions() diff --git a/examples/examples/scripts/test/orient.js b/examples/examples/scripts/test/orient.js new file mode 100644 index 000000000..02d47d12b --- /dev/null +++ b/examples/examples/scripts/test/orient.js @@ -0,0 +1,12 @@ + +stage.loadFile('data://1blu.pdb').then(function (o) { + o.addRepresentation('hyperball', { sele: 'hetero' }) + o.addRepresentation('cartoon') + + stage.viewerControls.orient([ + 5.16, -0.86, -8.11, 0, + 3.05, 9.11, 0.97, 0, + 7.56, -3.08, 5.15, 0, + -28.57, -13.64, 3.36, 1 + ]) +}) diff --git a/examples/examples/scripts/test/pbc.js b/examples/examples/scripts/test/pbc.js new file mode 100644 index 000000000..059baa199 --- /dev/null +++ b/examples/examples/scripts/test/pbc.js @@ -0,0 +1,9 @@ + +stage.loadFile('data://pbc.gro').then(function (o) { + // FIXME pbc centering and removal for files other then trajectories + + o.addRepresentation('cartoon', { sele: 'backbone' }) + o.addRepresentation('spacefill', { sele: 'backbone' }) + o.addRepresentation('line') + o.autoView() +}) diff --git a/examples/examples/scripts/test/pdbDaminoacids.js b/examples/examples/scripts/test/pdbDaminoacids.js new file mode 100644 index 000000000..ca74f84e6 --- /dev/null +++ b/examples/examples/scripts/test/pdbDaminoacids.js @@ -0,0 +1,14 @@ + +stage.loadFile('data://5gob.pdb', { + defaultAssembly: 'AU' +}).then(function (o) { + o.addRepresentation('cartoon', { + color: 'residueindex', + colorReverse: true + }) + o.addRepresentation('licorice', { + sele: 'ligand', + scale: 2.0 + }) + o.autoView() +}) diff --git a/examples/examples/scripts/test/pdbModifiedResidue.js b/examples/examples/scripts/test/pdbModifiedResidue.js new file mode 100644 index 000000000..af19e3d29 --- /dev/null +++ b/examples/examples/scripts/test/pdbModifiedResidue.js @@ -0,0 +1,12 @@ + +stage.loadFile('data://2src.pdb').then(function (o) { + o.addRepresentation('cartoon', { + color: 'residueindex', + colorReverse: true + }) + o.addRepresentation('licorice', { + sele: 'ligand', + scale: 2.0 + }) + o.autoView() +}) diff --git a/examples/examples/scripts/test/pickingImage.js b/examples/examples/scripts/test/pickingImage.js new file mode 100644 index 000000000..386556efe --- /dev/null +++ b/examples/examples/scripts/test/pickingImage.js @@ -0,0 +1,19 @@ + +stage.loadFile('data://3SN6.cif').then(function (o) { + o.addRepresentation('cartoon') + o.autoView() + + stage.viewer.getImage(true).then(function (blob) { + var size = stage.viewer.renderer.getSize() + var objectURL = window.URL.createObjectURL(blob) + var img = document.createElement('img') + img.src = objectURL + img.style.width = (size.width / 4) + 'px' + img.style.height = (size.height / 4) + 'px' + img.style.position = 'absolute' + img.style.top = '0px' + img.style.left = '0px' + img.style.zIndex = 10 + stage.viewer.container.appendChild(img) + }) +}) diff --git a/examples/examples/scripts/test/superposition.js b/examples/examples/scripts/test/superposition.js new file mode 100644 index 000000000..2d8464acd --- /dev/null +++ b/examples/examples/scripts/test/superposition.js @@ -0,0 +1,18 @@ + +Promise.all([ + stage.loadFile('data://sp-ido40.mol2').then(function (o) { + o.addRepresentation('ball+stick') + return o + }), + + stage.loadFile('data://sp-after.mol2').then(function (o) { + o.addRepresentation('licorice') + return o + }) +]).then(function (ol) { + var sp = new NGL.Superposition(ol[0].structure, ol[1].structure) + sp.transform(ol[0].structure) + ol[0].updateRepresentations({ 'position': true }) + console.log(sp) + ol[1].autoView() +}) diff --git a/examples/examples/scripts/test/timing.js b/examples/examples/scripts/test/timing.js new file mode 100644 index 000000000..a5478d8b0 --- /dev/null +++ b/examples/examples/scripts/test/timing.js @@ -0,0 +1,18 @@ + +// stage.loadFile( "data://3l5q.pdb", function( o ){ +stage.loadFile('data://4UJD.cif.gz').then(function (o) { +// stage.loadFile( "data://3j3y.cif.gz", function( o ){ + + // o.addRepresentation( "line", { color: "chainindex" } ); + // o.addRepresentation( "spacefill", { color: "chainindex" } ); + o.addRepresentation('cartoon', { color: 'chainindex' }) + // o.addRepresentation( "trace", { color: "chainindex" } ); + // o.addRepresentation( "point", { color: "chainindex" } ); + stage.autoView() + + console.timeEnd('test') + + console.time('render') + o.viewer.render() + console.timeEnd('render') +}) diff --git a/examples/examples/scripts/test/xray.js b/examples/examples/scripts/test/xray.js new file mode 100644 index 000000000..5c1028134 --- /dev/null +++ b/examples/examples/scripts/test/xray.js @@ -0,0 +1,42 @@ + +stage.setParameters({ + cameraType: 'orthographic', + mousePreset: 'coot' +}) + +stage.loadFile('data://3ek3.cif').then(function (o) { + o.addRepresentation('licorice', { + colorValue: 'yellow', + roughness: 1.0 + }) + o.autoView('FMN') + stage.setFocus(97) +}) + +stage.loadFile('data://3ek3-2fofc.map.gz').then(function (o) { + o.addRepresentation('surface', { + color: 'skyblue', + isolevel: 1.5, + boxSize: 10, + useWorker: false, + contour: true + }) +}) + +stage.loadFile('data://3ek3-fofc.map.gz').then(function (o) { + o.addRepresentation('surface', { + color: 'lightgreen', + isolevel: 3, + boxSize: 10, + useWorker: false, + contour: true + }) + o.addRepresentation('surface', { + color: 'tomato', + isolevel: 3, + negateIsolevel: true, + boxSize: 10, + useWorker: false, + contour: true + }) +}) diff --git a/examples/examples/test.html b/examples/examples/test.html new file mode 100644 index 000000000..0cdf9dd3f --- /dev/null +++ b/examples/examples/test.html @@ -0,0 +1,34 @@ + + + + NGL - test + + + + + + + +
+ + diff --git a/examples/examples/webapp.html b/examples/examples/webapp.html new file mode 100644 index 000000000..bf6ec429d --- /dev/null +++ b/examples/examples/webapp.html @@ -0,0 +1,64 @@ + + + + NGL - webapp + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/controls/mouse-actions.ts b/src/controls/mouse-actions.ts index 9bda6b2b0..687f26d1c 100644 --- a/src/controls/mouse-actions.ts +++ b/src/controls/mouse-actions.ts @@ -188,6 +188,14 @@ class MouseActions { stage.trackballControls.translateAtoms(dx, dy) } + /** + * Rotate picked component based on mouse coordinate changes. + * Doesn't work very well. + * @param {Stage} stage + * @param {Number} dx - amount to move in x direction + * @param {Number} dy - amount to move in y direction + * @return {undefined} + */ static rotateSelectionDrag(stage: Stage, dx: number, dy: number) { stage.trackballControls.rotateAtoms(dx, dy) } @@ -311,57 +319,60 @@ class MouseActions { type MouseActionPreset = [string, MouseActionCallback][] export const MouseActionPresets = { default: [ - // [ 'scroll', MouseActions.zoomScroll ], - // [ 'scroll-shift', MouseActions.focusScroll ], - // [ 'scroll-ctrl', MouseActions.isolevelScroll ], - // [ 'scroll-shift-ctrl', MouseActions.zoomFocusScroll ], - - // [ 'drag-left', MouseActions.rotateDrag ], - // [ 'drag-right', MouseActions.panDrag ], - // [ 'drag-ctrl-left', MouseActions.panDrag ], - // [ 'drag-ctrl-right', MouseActions.zRotateDrag ], - // [ 'drag-shift-left', MouseActions.zoomDrag ], - // [ 'drag-middle', MouseActions.zoomFocusDrag ], - - // [ 'drag-ctrl-shift-right', MouseActions.panComponentDrag ], - // [ 'drag-ctrl-shift-left', MouseActions.rotateComponentDrag ], - - // [ 'clickPick-right', MouseActions.measurePick ], - // [ 'clickPick-ctrl-left', MouseActions.measurePick ], - // [ 'clickPick-middle', MouseActions.movePick ], - // [ 'clickPick-left', MouseActions.movePick ], - // [ 'hoverPick', MouseActions.tooltipPick ] - // ] as MouseActionPreset, - // pymol: [ - // [ 'drag-left', MouseActions.rotateDrag ], - // [ 'drag-middle', MouseActions.panDrag ], - // [ 'drag-right', MouseActions.zoomDrag ], - // [ 'drag-shift-right', MouseActions.focusScroll ], - - // [ 'clickPick-ctrl+shift-middle', MouseActions.movePick ], - // [ 'hoverPick', MouseActions.tooltipPick ] - // ] as MouseActionPreset, - // coot: [ - // [ 'scroll', MouseActions.isolevelScroll ], - - // [ 'drag-left', MouseActions.rotateDrag ], - // [ 'drag-middle', MouseActions.panDrag ], - // [ 'drag-ctrl-left', MouseActions.panDrag ], - // [ 'drag-right', MouseActions.zoomFocusDrag ], - // [ 'drag-ctrl-right', MouseActions.focusScroll ], - - // [ 'clickPick-middle', MouseActions.movePick ], - // [ 'hoverPick', MouseActions.tooltipPick ] - // ] as MouseActionPreset, - // astexviewer: [ - // [ 'drag-left', MouseActions.rotateDrag ], - // [ 'drag-ctrl-left', MouseActions.panDrag ], - // [ 'drag-shift-left', MouseActions.zoomDrag ], - // [ 'scroll', MouseActions.focusScroll ], - // [ 'clickPick-middle', MouseActions.movePick ], - // [ 'hoverPick', MouseActions.tooltipPick ] - // ] as MouseActionPreset, - // iqmol: [ + ['scroll', MouseActions.zoomScroll], + ['scroll-shift', MouseActions.focusScroll], + ['scroll-ctrl', MouseActions.isolevelScroll], + ['scroll-shift-ctrl', MouseActions.zoomFocusScroll], + + ['drag-left', MouseActions.rotateDrag], + ['drag-right', MouseActions.panDrag], + ['drag-ctrl-left', MouseActions.panDrag], + ['drag-ctrl-right', MouseActions.zRotateDrag], + ['drag-shift-left', MouseActions.zoomDrag], + ['drag-middle', MouseActions.zoomFocusDrag], + + ['drag-ctrl-shift-right', MouseActions.moveComponentDrag], + ['drag-ctrl-shift-left', MouseActions.rotateComponentDrag], + + ['clickPick-shift-left', MouseActions.selectPick], + ['doubleClick-shift-left', MouseActions.clearSelect], + + ['clickPick-right', MouseActions.measurePick], + ['clickPick-ctrl-left', MouseActions.measurePick], + ['clickPick-middle', MouseActions.movePick], + ['clickPick-left', MouseActions.movePick], + ['hoverPick', MouseActions.tooltipPick] + ] as MouseActionPreset, + pymol: [ + ['drag-left', MouseActions.rotateDrag], + ['drag-middle', MouseActions.panDrag], + ['drag-right', MouseActions.zoomDrag], + ['drag-shift-right', MouseActions.focusScroll], + + ['clickPick-ctrl+shift-middle', MouseActions.movePick], + ['hoverPick', MouseActions.tooltipPick] + ] as MouseActionPreset, + coot: [ + ['scroll', MouseActions.isolevelScroll], + + ['drag-left', MouseActions.rotateDrag], + ['drag-middle', MouseActions.panDrag], + ['drag-ctrl-left', MouseActions.panDrag], + ['drag-right', MouseActions.zoomFocusDrag], + ['drag-ctrl-right', MouseActions.focusScroll], + + ['clickPick-middle', MouseActions.movePick], + ['hoverPick', MouseActions.tooltipPick] + ] as MouseActionPreset, + astexviewer: [ + ['drag-left', MouseActions.rotateDrag], + ['drag-ctrl-left', MouseActions.panDrag], + ['drag-shift-left', MouseActions.zoomDrag], + ['scroll', MouseActions.focusScroll], + ['clickPick-middle', MouseActions.movePick], + ['hoverPick', MouseActions.tooltipPick] + ] as MouseActionPreset, + iqmol: [ ['scroll', MouseActions.zoomScroll], ['scroll-shift', MouseActions.focusScroll], ['scroll-ctrl', MouseActions.isolevelScroll], From c14a7446105de9f0417098ad849765fe140362ed Mon Sep 17 00:00:00 2001 From: Lily Wang Date: Tue, 18 Jun 2019 14:33:46 +1000 Subject: [PATCH 11/16] tidied --- doc/usage/interaction-controls.md | 20 ++---- src/controls/mouse-actions.ts | 77 +------------------- src/controls/picking-controls.ts | 20 ------ src/stage/mouse-observer.ts | 12 +--- src/stage/picking-behavior.ts | 8 +-- src/stage/selecting-behavior.ts | 64 ----------------- src/stage/stage.ts | 113 ++++++++++++++---------------- src/ui/parameters.ts | 17 +++-- src/viewer/drag-selection.ts | 77 -------------------- src/viewer/viewer.ts | 63 ----------------- 10 files changed, 72 insertions(+), 399 deletions(-) delete mode 100644 src/stage/selecting-behavior.ts delete mode 100644 src/viewer/drag-selection.ts diff --git a/doc/usage/interaction-controls.md b/doc/usage/interaction-controls.md index 8d15af121..9bde61801 100644 --- a/doc/usage/interaction-controls.md +++ b/doc/usage/interaction-controls.md @@ -151,24 +151,12 @@ The default controls are as follows: - `drag-ctrl-left` rotate hovered component - `clickPick-middle` auto view picked component element - `hoverPick` show tooltip for hovered component element +- `clickPick-shift-left` de/select an atom +- `doubleClick-shift-left` clear selected atoms +- `drag-shift-left` move selected atoms -Four presets are available: "default", "coot", "astexviewer", and "iqmol". The iqmol preset allows you to select atoms and drag them to edit their positions. - -The iqmol controls are as follows: -- `scroll` zoom scene -- `scroll-ctrl` move near clipping plane -- `scroll-shift` move near clipping plane and far fog -- `scroll-alt` change isolevel of isosurfaces -- `drag-right` pan/translate scene -- `drag-left` rotate scene -- `drag-middle` zoom scene -- `drag-shift-left` select atoms via lasso -- `drag-ctrl-right` drag selected atoms -- `drag-ctrl-left` rotate selected atoms -- `doubleClick-shift-left` clear selected atoms -- `clickPick-middle` auto view picked component element -- `hoverPick` show tooltip for hovered component element +Four presets are available: "default", "coot", and "astexviewer". ### Observer diff --git a/src/controls/mouse-actions.ts b/src/controls/mouse-actions.ts index b5b825244..c3c2d9171 100644 --- a/src/controls/mouse-actions.ts +++ b/src/controls/mouse-actions.ts @@ -9,7 +9,6 @@ import { almostIdentity } from '../math/math-utils' import Stage from '../stage/stage' import StructureComponent from '../component/structure-component' import SurfaceRepresentation from '../representation/surface-representation' -import { SimpleSet, createSimpleSet } from '../utils'; export type ScrollCallback = (stage: Stage, delta: number) => void export type DragCallback = (stage: Stage, dx: number, dy: number) => void @@ -190,7 +189,7 @@ class MouseActions { /** * Rotate picked component based on mouse coordinate changes. - * Doesn't work very well. + * Doesn't work very well; not implemented in mouse presets. * @param {Stage} stage * @param {Number} dx - amount to move in x direction * @param {Number} dy - amount to move in y direction @@ -233,7 +232,6 @@ class MouseActions { } - static measurePick(stage: Stage, pickingProxy: PickingProxy) { if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) { const atom = pickingProxy.atom || pickingProxy.closestBondAtom @@ -258,57 +256,12 @@ class MouseActions { } } - static selectPickAll(stage: Stage, pickingProxies: PickingProxy[]) { - let components: StructureComponent[] = [] - let picked: SimpleSet[] = [] - - stage.dragSelection.removeSelection() - - pickingProxies.forEach(function (pickingProxy) { - if (pickingProxy && pickingProxy.atom) { - let a = pickingProxy.atom.index - let sc = pickingProxy.component as StructureComponent - - if (!components.includes(sc)) { - let _new = createSimpleSet() - components.push(sc) - picked.push(_new) - } - - let j = components.indexOf(sc) - picked[j].add(a) - } - }) - for (var i = 0; i < components.length; i++) { - components[i].selectedPickIndices(picked[i].list) - } - } - - static onDragXY(stage: Stage, x: number, y: number) { - stage.dragSelection.moveSelection(x, y) - } - static clearSelect(stage: Stage) { stage.eachComponent(function (sc: StructureComponent) { sc.selectedAtomIndices.clear() sc.selectedUpdate() }, "structure") } - - static onSelectDown(stage: Stage, x: number, y: number) { - const ds = stage.dragSelection - const sp = stage.getParameters() as any - if (sp.dragSelection) { - ds.createSelection(x, y) - } else { - ds.removeSelection() - } - } - - static onSelectUp(stage: Stage) { - stage.dragSelection.removeSelection() - } - } type MouseActionPreset = [string, MouseActionCallback][] @@ -323,12 +276,10 @@ export const MouseActionPresets = { ['drag-right', MouseActions.panDrag], ['drag-ctrl-left', MouseActions.panDrag], ['drag-ctrl-right', MouseActions.zRotateDrag], + ['drag-shift-right', MouseActions.moveComponentDrag], ['drag-shift-left', MouseActions.zoomDrag], ['drag-middle', MouseActions.zoomFocusDrag], - ['drag-ctrl-shift-right', MouseActions.moveComponentDrag], - ['drag-ctrl-shift-left', MouseActions.rotateComponentDrag], - ['clickPick-shift-left', MouseActions.selectPick], ['doubleClick-shift-left', MouseActions.clearSelect], @@ -366,30 +317,6 @@ export const MouseActionPresets = { ['scroll', MouseActions.focusScroll], ['clickPick-middle', MouseActions.movePick], ['hoverPick', MouseActions.tooltipPick] - ] as MouseActionPreset, - iqmol: [ - ['scroll', MouseActions.zoomScroll], - ['scroll-shift', MouseActions.focusScroll], - ['scroll-ctrl', MouseActions.isolevelScroll], - ['scroll-shift-ctrl', MouseActions.zoomFocusScroll], - - ['press-shift-left', MouseActions.onSelectDown], - ['drop-shift-left', MouseActions.selectPickAll], - ['drop-left', MouseActions.selectPickAll], - - ['drag-left', MouseActions.rotateDrag], - ['drag-right', MouseActions.panDrag], - ['drag-ctrl-left', MouseActions.rotateSelectionDrag], - ['drag-ctrl-right', MouseActions.moveComponentDrag], - ['dragXY-shift-left', MouseActions.onDragXY], - ['drag-middle', MouseActions.zoomFocusDrag], - - ['clickPick-shift-left', MouseActions.selectPick], - ['doubleClick-shift-left', MouseActions.clearSelect], - - ['clickPick-right', MouseActions.measurePick], - ['clickPick-middle', MouseActions.movePick], - ['hoverPick', MouseActions.tooltipPick] ] as MouseActionPreset } diff --git a/src/controls/picking-controls.ts b/src/controls/picking-controls.ts index 11a710471..415edb097 100644 --- a/src/controls/picking-controls.ts +++ b/src/controls/picking-controls.ts @@ -39,26 +39,6 @@ class PickingControls { } } } - - pickAll(x0: number, y0: number, x1: number, y1: number) { - const pickedData = this.viewer.pickAll(x0, y0, x1, y1) - let picked: PickingProxy[] = [] - - for (var i = 0; i < pickedData.length; i++) { - let pickingData = pickedData[i] - if (pickingData.picker.type !== 'ignore' && - pickingData.pid !== undefined - ) { - let pickerArray = pickingData.picker.array - if (pickerArray && pickingData.pid >= pickerArray.length) { - console.error('pid >= picker.array.length') - } else { - picked.push(new PickingProxy(pickingData, this.stage)) - } - } - } - return picked - } } export default PickingControls diff --git a/src/stage/mouse-observer.ts b/src/stage/mouse-observer.ts index ba020140b..fdd9560bd 100644 --- a/src/stage/mouse-observer.ts +++ b/src/stage/mouse-observer.ts @@ -66,8 +66,7 @@ export interface MouseSignals { dropped: Signal // on drop clicked: Signal // on click hovered: Signal // on hover - doubleClicked: Signal - pressed: Signal + doubleClicked: Signal // on double click } export interface MouseParams { @@ -113,7 +112,6 @@ class MouseObserver { clicked: new Signal(), hovered: new Signal(), doubleClicked: new Signal(), - pressed: new Signal(), } hoverTimeout: number @@ -283,12 +281,6 @@ class MouseObserver { this.signals.moved.dispatch(dx, dy) if (this.pressed) { this.signals.dragged.dispatch(dx, dy) - this.signals.draggedXY.dispatch( - this.prevPosition.x, - this.prevPosition.y, - this.canvasPosition.x, - this.canvasPosition.y - ) } } @@ -306,7 +298,6 @@ class MouseObserver { this.buttons = getMouseButtons(event) this.pressed = true this._setCanvasPosition(event) - this.signals.pressed.dispatch(event.clientX, event.clientY) } /** @@ -320,7 +311,6 @@ class MouseObserver { if (event.target === this.domElement) { event.preventDefault() } - this.signals.dropped.dispatch(event.clientX, event.clientY); this._setKeys(event) const cp = this.canvasPosition this.signals.dropped.dispatch(); diff --git a/src/stage/picking-behavior.ts b/src/stage/picking-behavior.ts index a92c44e3d..f157f04fe 100644 --- a/src/stage/picking-behavior.ts +++ b/src/stage/picking-behavior.ts @@ -14,7 +14,7 @@ class PickingBehavior { mouse: MouseObserver controls: MouseControls - constructor (readonly stage: Stage) { + constructor(readonly stage: Stage) { this.stage = stage this.mouse = stage.mouseObserver this.controls = stage.mouseControls @@ -23,13 +23,13 @@ class PickingBehavior { this.mouse.signals.hovered.add(this._onHover, this) } - _onClick (x: number, y: number) { + _onClick(x: number, y: number) { const pickingProxy = this.stage.pickingControls.pick(x, y) this.stage.signals.clicked.dispatch(pickingProxy) this.controls.run('clickPick', pickingProxy) } - _onHover (x: number, y: number) { + _onHover(x: number, y: number) { const pickingProxy = this.stage.pickingControls.pick(x, y) if (pickingProxy && this.mouse.down.equals(this.mouse.position)) { this.stage.transformComponent = pickingProxy.component @@ -39,7 +39,7 @@ class PickingBehavior { this.controls.run('hoverPick', pickingProxy) } - dispose () { + dispose() { this.mouse.signals.clicked.remove(this._onClick, this) this.mouse.signals.hovered.remove(this._onHover, this) } diff --git a/src/stage/selecting-behavior.ts b/src/stage/selecting-behavior.ts deleted file mode 100644 index b3cfa4521..000000000 --- a/src/stage/selecting-behavior.ts +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @file Selecting Behavior - * @author Lily Wang - * @private - */ - -import Stage from './stage' -import MouseObserver from './mouse-observer' -import Viewer from '../viewer/viewer' -import MouseControls from '../controls/mouse-controls' - -class SelectingBehavior { - viewer: Viewer - mouse: MouseObserver - controls: MouseControls - - constructor(readonly stage: Stage) { - this.stage = stage - this.mouse = stage.mouseObserver - this.controls = stage.mouseControls - - // this.mouse.signals.clicked.add(this._onClick, this) - this.mouse.signals.pressed.add(this._onPress, this) - this.mouse.signals.draggedXY.add(this._onDragXY, this) - this.mouse.signals.dropped.add(this._onDrop, this) - // this.mouse.signals.doubleClicked.add(this._onDoubleClick, this) - } - - // _onClick (x: number, y: number) { - // const pickingProxy = this.stage.pickingControls.pick(x, y) - // this.stage.signals.clicked.dispatch(pickingProxy) - // this.controls.run('clickPick', pickingProxy) - // } - - _onPress(x: number, y: number) { - this.controls.run('press', x, y) - } - - _onDrop(x: number, y: number) { - if (this.stage.dragSelection.isDown) { - const x0 = this.stage.dragSelection.startPoint.x - const y0 = this.stage.dragSelection.startPoint.y - let pickedProxies = this.stage.pickingControls.pickAll(x0, y0, x, y) - this.controls.run('drop', pickedProxies) - } - } - - _onDragXY(x1: number, y1: number) { - // const sp = this.stage.getParameters() as any - if (this.stage.dragSelection.isDown) { - this.controls.run('dragXY', x1, y1) - } - } - - dispose() { - // this.mouse.signals.clicked.remove(this._onClick, this) - this.mouse.signals.pressed.remove(this._onPress, this) - this.mouse.signals.draggedXY.remove(this._onDragXY, this) - this.mouse.signals.dropped.remove(this._onDrop, this) - // this.mouse.signals.doubleClicked.remove(this._onDoubleClick, this) - } -} - -export default SelectingBehavior diff --git a/src/stage/stage.ts b/src/stage/stage.ts index 78a670c4c..0b57c28be 100644 --- a/src/stage/stage.ts +++ b/src/stage/stage.ts @@ -15,7 +15,6 @@ import { degToRad, clamp, pclamp } from '../math/math-utils' import Counter from '../utils/counter' import Viewer from '../viewer/viewer' import { ImageParameters } from '../viewer/viewer-utils' -import DragSelection from '../viewer/drag-selection' import MouseObserver from './mouse-observer' import TrackballControls from '../controls/trackball-controls' @@ -26,7 +25,6 @@ import MouseControls, { MouseControlPreset } from '../controls/mouse-controls' import KeyControls from '../controls/key-controls' import PickingBehavior from './picking-behavior' -import SelectingBehavior from './selecting-behavior' import MouseBehavior from './mouse-behavior' import AnimationBehavior from './animation-behavior' import KeyBehavior from './key-behavior' @@ -49,7 +47,7 @@ import Volume from '../surface/volume' import Shape from '../geometry/shape' import Script from '../script' -function matchName (name: string|RegExp, object: { name: string }) { +function matchName(name: string | RegExp, object: { name: string }) { if (name instanceof RegExp) { return object.name.match(name) !== null } else { @@ -115,14 +113,14 @@ export interface StageSignals { hovered: Signal } -export type RenderQualityType = 'auto'|'low'|'medium'|'high' +export type RenderQualityType = 'auto' | 'low' | 'medium' | 'high' export const StageDefaultParameters = { impostor: true, quality: 'medium' as RenderQualityType, workerDefault: true, sampleLevel: 0, - backgroundColor: 'black' as string|number, + backgroundColor: 'black' as string | number, rotateSpeed: 2.0, zoomSpeed: 1.2, panSpeed: 1.0, @@ -133,14 +131,13 @@ export const StageDefaultParameters = { fogFar: 100, cameraFov: 40, cameraEyeSep: 0.3, - cameraType: 'perspective' as 'perspective'|'orthographic'|'stereo', - lightColor: 0xdddddd as string|number, + cameraType: 'perspective' as 'perspective' | 'orthographic' | 'stereo', + lightColor: 0xdddddd as string | number, lightIntensity: 1.0, - ambientColor: 0xdddddd as string|number, + ambientColor: 0xdddddd as string | number, ambientIntensity: 0.2, hoverTimeout: 0, tooltip: true, - dragSelection: true, mousePreset: 'default' as MouseControlPreset } export type StageParameters = typeof StageDefaultParameters @@ -180,7 +177,6 @@ class Stage { viewer: Viewer tooltip: HTMLElement - dragSelection: DragSelection lastFullscreenElement: HTMLElement mouseObserver: MouseObserver @@ -192,7 +188,6 @@ class Stage { keyControls: KeyControls pickingBehavior: PickingBehavior - selectingBehavior: SelectingBehavior mouseBehavior: MouseBehavior animationBehavior: AnimationBehavior keyBehavior: KeyBehavior @@ -200,7 +195,7 @@ class Stage { spinAnimation: Animation rockAnimation: Animation - constructor (idOrElement: string|HTMLElement, params: Partial = {}) { + constructor(idOrElement: string | HTMLElement, params: Partial = {}) { this.viewer = new Viewer(idOrElement) if (!this.viewer.renderer) return @@ -217,7 +212,6 @@ class Stage { }) this.viewer.container.appendChild(this.tooltip) - this.dragSelection = new DragSelection(this.viewer) this.mouseObserver = new MouseObserver(this.viewer.renderer.domElement) this.viewerControls = new ViewerControls(this) @@ -228,14 +222,13 @@ class Stage { this.keyControls = new KeyControls(this) this.pickingBehavior = new PickingBehavior(this) - this.selectingBehavior = new SelectingBehavior(this) this.mouseBehavior = new MouseBehavior(this) this.animationBehavior = new AnimationBehavior(this) this.keyBehavior = new KeyBehavior(this) - this.spinAnimation = this.animationControls.spin([ 0, 1, 0 ], 0.005) + this.spinAnimation = this.animationControls.spin([0, 1, 0], 0.005) this.spinAnimation.pause(true) - this.rockAnimation = this.animationControls.rock([ 0, 1, 0 ], 0.005) + this.rockAnimation = this.animationControls.rock([0, 1, 0], 0.005) this.rockAnimation.pause(true) // must come after the viewer has been instantiated @@ -248,7 +241,7 @@ class Stage { /** * Set stage parameters */ - setParameters (params: Partial = {}) { + setParameters(params: Partial = {}) { updateParams(this.parameters, params) const p = params @@ -277,7 +270,7 @@ class Stage { return this } - log (msg: string) { + log(msg: string) { console.log('STAGE LOG', msg) this.logList.push(msg) } @@ -285,7 +278,7 @@ class Stage { /** * Get stage parameters */ - getParameters () { + getParameters() { return Object.assign({}, this.parameters) } @@ -294,7 +287,7 @@ class Stage { * @param {StructureComponent|SurfaceComponent} object - component to create the representations for * @return {undefined} */ - defaultFileRepresentation (component: Component) { + defaultFileRepresentation(component: Component) { if (component instanceof StructureComponent) { component.setSelection('/0') @@ -452,14 +445,14 @@ class Stage { * a {@link SurfaceComponent} or a {@link ScriptComponent} object, * depending on the type of the loaded file. */ - loadFile (path: string|File|Blob, params: Partial = {}) { + loadFile(path: string | File | Blob, params: Partial = {}) { const p = Object.assign({}, this.defaultFileParams, params) const name = getFileInfo(path).name this.tasks.increment() this.log(`loading file '${name}'`) - const onLoadFn = (object: Structure|Surface|Volume) => { + const onLoadFn = (object: Structure | Surface | Volume) => { this.log(`loaded '${name}'`) const component = this.addComponentFromObject(object, p) @@ -471,7 +464,7 @@ class Stage { return component } - const onErrorFn = (e: Error|string) => { + const onErrorFn = (e: Error | string) => { this.tasks.decrement() const errorMsg = `error loading file: '${e}'` this.log(errorMsg) @@ -492,7 +485,7 @@ class Stage { return promise.then(onLoadFn, onErrorFn) } - loadScript (path: string|File|Blob) { + loadScript(path: string | File | Blob) { const name = getFileInfo(path).name this.log(`loading script '${name}'`) @@ -507,7 +500,7 @@ class Stage { }) this.log(`called script '${name}'`) }, - (error: Error|string) => { + (error: Error | string) => { this.tasks.decrement() const errorMsg = `errored script '${name}' "${error}"` this.log(errorMsg) @@ -521,7 +514,7 @@ class Stage { * @param {Component} component - the component to add * @return {undefined} */ - addComponent (component: Component) { + addComponent(component: Component) { if (!component) { Log.warn('Stage.addComponent: no component given') return @@ -534,7 +527,7 @@ class Stage { /** * Create a component from the given object and add to the stage */ - addComponentFromObject (object: Structure|Surface|Volume|Shape, params: Partial = {}) { + addComponentFromObject(object: Structure | Surface | Volume | Shape, params: Partial = {}) { const CompClass = ComponentRegistry.get(object.type) if (CompClass) { @@ -551,7 +544,7 @@ class Stage { * @param {Component} component - the component to remove * @return {undefined} */ - removeComponent (component: Component) { + removeComponent(component: Component) { const idx = this.compList.indexOf(component) if (idx !== -1) { this.compList.splice(idx, 1) @@ -563,7 +556,7 @@ class Stage { /** * Remove all components from the stage */ - removeAllComponents () { + removeAllComponents() { this.compList.slice().forEach(o => this.removeComponent(o)) } @@ -571,7 +564,7 @@ class Stage { * Handle any size-changes of the container element * @return {undefined} */ - handleResize () { + handleResize() { this.viewer.handleResize() } @@ -581,7 +574,7 @@ class Stage { * @param {String} height - CSS height value * @return {undefined} */ - setSize (width: string, height: string) { + setSize(width: string, height: string) { const container = this.viewer.container if (container !== document.body) { @@ -597,9 +590,9 @@ class Stage { * defaults to the viewer container * @return {undefined} */ - toggleFullscreen (element: HTMLElement) { + toggleFullscreen(element: HTMLElement) { if (!document.fullscreenEnabled && !document.mozFullScreenEnabled && - !document.webkitFullscreenEnabled && !document.msFullscreenEnabled + !document.webkitFullscreenEnabled && !document.msFullscreenEnabled ) { Log.log('fullscreen mode (currently) not possible') return @@ -611,12 +604,12 @@ class Stage { // - function getFullscreenElement () { + function getFullscreenElement() { return document.fullscreenElement || document.mozFullScreenElement || - document.webkitFullscreenElement || document.msFullscreenElement + document.webkitFullscreenElement || document.msFullscreenElement } - function resizeElement () { + function resizeElement() { if (!getFullscreenElement() && self.lastFullscreenElement) { const element = self.lastFullscreenElement element.style.width = element.dataset.normalWidth || '' @@ -678,7 +671,7 @@ class Stage { * @param {Boolean} flag - if true start rocking and stop spinning * @return {undefined} */ - setSpin (flag: boolean) { + setSpin(flag: boolean) { if (flag) { this.spinAnimation.resume(true) this.rockAnimation.pause(true) @@ -692,7 +685,7 @@ class Stage { * @param {Boolean} flag - if true start rocking and stop spinning * @return {undefined} */ - setRock (flag: boolean) { + setRock(flag: boolean) { if (flag) { this.rockAnimation.resume(true) this.spinAnimation.pause(true) @@ -705,7 +698,7 @@ class Stage { * Toggle spin * @return {undefined} */ - toggleSpin () { + toggleSpin() { this.setSpin(this.spinAnimation.paused) } @@ -713,11 +706,11 @@ class Stage { * Toggle rock * @return {undefined} */ - toggleRock () { + toggleRock() { this.setRock(this.rockAnimation.paused) } - setFocus (value: number) { + setFocus(value: number) { const clipNear = clamp(value / 2, 0, 49.9) const clipFar = 100 - clipNear const diffHalf = (clipFar - clipNear) / 2 @@ -730,7 +723,7 @@ class Stage { }) } - getZoomForBox (boundingBox: Box3) { + getZoomForBox(boundingBox: Box3) { const bbSize = boundingBox.getSize(tmpZoomVector) const maxSize = Math.max(bbSize.x, bbSize.y, bbSize.z) const minSize = Math.min(bbSize.x, bbSize.y, bbSize.z) @@ -749,15 +742,15 @@ class Stage { return -distance } - getBox () { + getBox() { return this.viewer.boundingBox } - getZoom () { + getZoom() { return this.getZoomForBox(this.getBox()) } - getCenter (optionalTarget?: Vector3) { + getCenter(optionalTarget?: Vector3) { return this.getBox().getCenter(optionalTarget || new Vector3()) } @@ -766,7 +759,7 @@ class Stage { * @param {Integer} duration - animation time in milliseconds * @return {undefined} */ - autoView (duration?: number) { + autoView(duration?: number) { this.animationControls.zoomMove( this.getCenter(), this.getZoom(), @@ -777,7 +770,7 @@ class Stage { /** * Make image from what is shown in a viewer canvas */ - makeImage (params: Partial = {}) { + makeImage(params: Partial = {}) { return new Promise((resolve, reject) => { this.tasks.onZeroOnce(() => { this.tasks.increment() @@ -792,7 +785,7 @@ class Stage { }) } - setImpostor (value: boolean) { + setImpostor(value: boolean) { this.parameters.impostor = value const types = [ @@ -810,7 +803,7 @@ class Stage { }) } - setQuality (value: RenderQualityType) { + setQuality(value: RenderQualityType) { this.parameters.quality = value const types = [ @@ -843,7 +836,7 @@ class Stage { /** * Iterator over each component and executing the callback */ - eachComponent (callback: (comp: Component) => void, type?: string) { + eachComponent(callback: (comp: Component) => void, type?: string) { this.compList.slice().forEach(comp => { if (type === undefined || type === comp.type) callback(comp) }) @@ -852,7 +845,7 @@ class Stage { /** * Iterator over each representation and executing the callback */ - eachRepresentation (callback: (reprElem: RepresentationElement, comp: Component) => void, type?: string) { + eachRepresentation(callback: (reprElem: RepresentationElement, comp: Component) => void, type?: string) { this.eachComponent(comp => { comp.reprList.slice().forEach(reprElem => { if (type === undefined || type === reprElem.getType()) callback(reprElem, comp) @@ -863,7 +856,7 @@ class Stage { /** * Get collection of components by name */ - getComponentsByName (name: string|RegExp) { + getComponentsByName(name: string | RegExp) { const compList: Component[] = [] this.eachComponent(comp => { @@ -876,7 +869,7 @@ class Stage { /** * Get collection of components by object */ - getComponentsByObject (object: Structure|Surface|Volume|Shape) { + getComponentsByObject(object: Structure | Surface | Volume | Shape) { const compList: Component[] = [] this.eachComponent(comp => { @@ -889,7 +882,7 @@ class Stage { /** * Get collection of representations by name */ - getRepresentationsByName (name: string|RegExp) { + getRepresentationsByName(name: string | RegExp) { const reprList: RepresentationElement[] = [] this.eachRepresentation((repr, comp) => { @@ -899,19 +892,19 @@ class Stage { return new RepresentationCollection(reprList) } - measureClear () { + measureClear() { this.eachComponent((sc: StructureComponent) => sc.measureClear(), 'structure') } - measureUpdate () { + measureUpdate() { this.eachComponent((sc: StructureComponent) => sc.measureUpdate(), 'structure') } - selectedUpdate () { + selectedUpdate() { this.eachComponent((sc: StructureComponent) => sc.selectedUpdate(), 'structure') } - get selectedProxies () { + get selectedProxies() { let proxies: AtomProxy[] = []; this.eachComponent(function (sc: StructureComponent) { sc.selectedAtomIndices.list.forEach(function (i) { @@ -922,7 +915,7 @@ class Stage { return proxies } - get structureComponents () { + get structureComponents() { let comps: StructureComponent[] = []; this.eachComponent(function (sc: StructureComponent) { comps.push(sc) @@ -934,7 +927,7 @@ class Stage { /** * Cleanup when disposing of a stage object */ - dispose () { + dispose() { this.tasks.dispose() this.viewer.dispose() } diff --git a/src/ui/parameters.ts b/src/ui/parameters.ts index 703a7e19b..fcdbfa927 100644 --- a/src/ui/parameters.ts +++ b/src/ui/parameters.ts @@ -7,32 +7,32 @@ import { StageParameters } from '../stage/stage' import { MouseActionPresets } from '../controls/mouse-actions' export type BooleanParam = { type: 'boolean' } -function BooleanParam () { return { type: 'boolean' } as BooleanParam } +function BooleanParam() { return { type: 'boolean' } as BooleanParam } export type ColorParam = { type: 'color' } -function ColorParam () { return { type: 'color' } as ColorParam } +function ColorParam() { return { type: 'color' } as ColorParam } export type IntegerParam = { type: 'integer', max: number, min: number } -function IntegerParam (max: number, min: number) { +function IntegerParam(max: number, min: number) { return { type: 'integer', max, min } as IntegerParam } export type NumberParam = { type: 'number', precision: number, max: number, min: number } -function NumberParam (precision: number, max: number, min: number) { +function NumberParam(precision: number, max: number, min: number) { return { type: 'number', precision, max, min } as NumberParam } export type RangeParam = { type: 'range', step: number, max: number, min: number } -function RangeParam (step: number, max: number, min: number) { +function RangeParam(step: number, max: number, min: number) { return { type: 'range', step, max, min } as RangeParam } export type SelectParam = { type: 'select', options: { [k: string]: string } } -function SelectParam (...options: string[]) { - return { type: 'select', options: options.reduce((o, k) => ({ ...o, [k]: k}), {}) } as SelectParam +function SelectParam(...options: string[]) { + return { type: 'select', options: options.reduce((o, k) => ({ ...o, [k]: k }), {}) } as SelectParam } -export type ParamType = BooleanParam|ColorParam|IntegerParam|NumberParam|RangeParam|SelectParam +export type ParamType = BooleanParam | ColorParam | IntegerParam | NumberParam | RangeParam | SelectParam export const UIStageParameters: { [k in keyof StageParameters]: ParamType } = { backgroundColor: ColorParam(), @@ -57,6 +57,5 @@ export const UIStageParameters: { [k in keyof StageParameters]: ParamType } = { ambientIntensity: NumberParam(2, 10, 0), hoverTimeout: IntegerParam(10000, -1), tooltip: BooleanParam(), - dragSelection: BooleanParam(), mousePreset: SelectParam(...Object.keys(MouseActionPresets)) } diff --git a/src/viewer/drag-selection.ts b/src/viewer/drag-selection.ts deleted file mode 100644 index d5ab103b7..000000000 --- a/src/viewer/drag-selection.ts +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @file Selection-Box - * @author Lily Wang - * @private - */ - -import Viewer from './viewer' - -export default class DragSelection { - - viewer: Viewer - element: HTMLElement - - startPoint: { x: number, y: number }; - pointTopLeft: { x: number, y: number }; - pointBottomRight: { x: number, y: number }; - - isDown: Boolean; - - - constructor(viewer: Viewer) { - - this.viewer = viewer; - - this.element = document.createElement('div'); - - Object.assign(this.element.style, { - display: 'none', - position: 'fixed', - zIndex: '1000000', - pointerEvents: 'none', - border: '1px solid #55aaff', - backgroundColor: 'rgba(75, 160, 255, 0.3)', - }) - this.viewer.container.appendChild(this.element) - - this.startPoint = { x: 0, y: 0 }; - this.pointTopLeft = { x: 0, y: 0 }; - this.pointBottomRight = { x: 0, y: 0 }; - //TODO TOGGLE SET - this.isDown = false; - } - - createSelection(x: number, y: number) { - this.element.style.display = 'block'; - this.element.style.left = x + 'px'; - this.element.style.top = y + 'px'; - this.element.style.width = '0px'; - this.element.style.height = '0px'; - - this.startPoint.x = x; - this.startPoint.y = y; - - this.isDown = true; - } - - moveSelection(x: number, y: number) { - if (!this.isDown) return; - - this.pointBottomRight.x = Math.max(this.startPoint.x, x); - this.pointBottomRight.y = Math.max(this.startPoint.y, y); - this.pointTopLeft.x = Math.min(this.startPoint.x, x); - this.pointTopLeft.y = Math.min(this.startPoint.y, y); - - this.element.style.left = this.pointTopLeft.x + 'px'; - this.element.style.top = this.pointTopLeft.y + 'px'; - this.element.style.width = (this.pointBottomRight.x - this.pointTopLeft.x) + 'px'; - this.element.style.height = (this.pointBottomRight.y - this.pointTopLeft.y) + 'px'; - } - - removeSelection() { - this.element.style.display = 'none'; - this.isDown = false; - } - - -} \ No newline at end of file diff --git a/src/viewer/viewer.ts b/src/viewer/viewer.ts index 4e27ed62f..2fe981cbe 100644 --- a/src/viewer/viewer.ts +++ b/src/viewer/viewer.ts @@ -993,69 +993,6 @@ export default class Viewer { return { pid, instance, picker } } - pickAll(x0: number, y0: number, x1: number, y1: number) { - - if (this.parameters.cameraType === 'stereo') { - return [] - } - - let picked = [] - - x0 *= window.devicePixelRatio - y0 *= window.devicePixelRatio - x1 *= window.devicePixelRatio - y1 *= window.devicePixelRatio - - let x = Math.min(x0, x1) - let y = this.pickingTarget.height - Math.min(y0, y1) - - - let px = Math.abs(x1 - x0) - let py = Math.abs(y1 - y0) - - let _pixelBufferFloat = new Float32Array(4 * px * py) - let _pixelBufferUint = new Uint8Array(4 * px * py) - const pixelBuffer = SupportsReadPixelsFloat ? _pixelBufferFloat : _pixelBufferUint - - this.render(true) - this.renderer.readRenderTargetPixels( - this.pickingTarget, x, y, px, py, pixelBuffer - ) - - for (let i = 0; i < px * py; i++) { - - let pid: number = 0, instance, picker - - let offset = i * 4 - - const oid = Math.round(pixelBuffer[offset + 3]) - const object = this.pickingGroup.getObjectById(oid) - if (object) { - instance = object.userData.instance - picker = object.userData.buffer.picking - } else { - continue - } - - if (!picker) continue; - - if (SupportsReadPixelsFloat) { - pid = - ((Math.round(pixelBuffer[offset] * 255) << 16) & 0xFF0000) | - ((Math.round(pixelBuffer[offset + 1] * 255) << 8) & 0x00FF00) | - ((Math.round(pixelBuffer[offset + 2] * 255)) & 0x0000FF) - } else { - pid = - (pixelBuffer[offset] << 16) | - (pixelBuffer[offset + 1] << 8) | - (pixelBuffer[offset + 2]) - } - - picked.push({ pid, instance, picker }) - } - return picked - } - requestRender() { if (this.renderPending) { // Log.info("there is still a 'render' call pending") From fb2968d2e0d2ca4c44ce1316be2a89a920a36ae7 Mon Sep 17 00:00:00 2001 From: Lily Wang Date: Tue, 18 Jun 2019 14:35:51 +1000 Subject: [PATCH 12/16] updated user guide --- doc/usage/interaction-controls.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/usage/interaction-controls.md b/doc/usage/interaction-controls.md index 9bde61801..f0a860cfc 100644 --- a/doc/usage/interaction-controls.md +++ b/doc/usage/interaction-controls.md @@ -81,7 +81,6 @@ Note that the [MouseControls](../class/src/controls/mouse-controls.js~MouseContr stage.signals.clicked.add(function (pickingProxy) {...}); ``` - ### Hovered Basis usage: @@ -156,7 +155,7 @@ The default controls are as follows: - `drag-shift-left` move selected atoms -Four presets are available: "default", "coot", and "astexviewer". +Four presets are available: "default", "pymol", "coot", and "astexviewer". ### Observer From 165e0baecbb729066055f686827577193b336788 Mon Sep 17 00:00:00 2001 From: Lily Wang Date: Tue, 18 Jun 2019 14:52:32 +1000 Subject: [PATCH 13/16] removed accidental copy --- examples/examples/annotations.html | 57 - examples/examples/css/dark.css | 69 - examples/examples/css/font-awesome.min.css | 4 - examples/examples/css/light.css | 69 - examples/examples/css/main.css | 454 ---- examples/examples/embedded.html | 19 - examples/examples/fonts/FontAwesome.otf | Bin 75188 -> 0 bytes .../examples/fonts/fontawesome-webfont.eot | Bin 72449 -> 0 bytes .../examples/fonts/fontawesome-webfont.svg | 504 ---- .../examples/fonts/fontawesome-webfont.ttf | Bin 141564 -> 0 bytes .../examples/fonts/fontawesome-webfont.woff | Bin 83760 -> 0 bytes examples/examples/grid.html | 149 - examples/examples/js/gui.js | 2394 ----------------- examples/examples/js/lib/colorpicker.min.js | 14 - examples/examples/js/lib/signals.min.js | 14 - examples/examples/js/lib/tether.min.js | 3 - examples/examples/js/ui/ui.extra.js | 1136 -------- examples/examples/js/ui/ui.js | 1037 ------- examples/examples/js/ui/ui.ngl.js | 368 --- examples/examples/mobile.html | 56 - examples/examples/parallel.html | 33 - examples/examples/scripts/color/atomindex.js | 5 - examples/examples/scripts/color/bfactor.js | 5 - examples/examples/scripts/color/chainid.js | 5 - examples/examples/scripts/color/custom.js | 17 - .../examples/scripts/color/electrostatic.js | 9 - examples/examples/scripts/color/element.js | 5 - examples/examples/scripts/color/modelindex.js | 5 - .../examples/scripts/color/partialcharge.js | 5 - examples/examples/scripts/color/resname.js | 7 - examples/examples/scripts/color/selection.js | 25 - examples/examples/scripts/color/sstruc.js | 5 - examples/examples/scripts/color/volume-esp.js | 25 - examples/examples/scripts/color/volume.js | 27 - .../examples/scripts/component/getByName.js | 12 - examples/examples/scripts/component/matrix.js | 15 - .../scripts/component/shape-buffer.js | 19 - .../examples/scripts/component/shape-cat.js | 32 - .../scripts/component/shape-wireframe.js | 8 - examples/examples/scripts/component/shape.js | 23 - .../component/structure-autoChainName.js | 8 - .../scripts/component/structure-biomol.js | 12 - .../component/structure-biomolSimple.js | 11 - .../scripts/component/structure-bondOrders.js | 5 - .../component/structure-coarseGrained.js | 7 - .../scripts/component/structure-cyclic.js | 7 - .../scripts/component/structure-dna.js | 14 - .../scripts/component/structure-multiModel.js | 15 - .../scripts/component/structure-superpose.js | 25 - .../examples/scripts/component/transform.js | 21 - .../scripts/interactive/annotation.js | 31 - .../scripts/interactive/crosslinking.js | 884 ------ .../scripts/interactive/hover-tooltip.js | 34 - .../scripts/interactive/interpolate.js | 20 - .../scripts/interactive/ligand-viewer.js | 627 ----- .../scripts/interactive/simple-viewer.js | 125 - .../scripts/interactive/xray-viewer.js | 455 ---- examples/examples/scripts/parser/brix.js | 10 - examples/examples/scripts/parser/ccp4.js | 48 - .../examples/scripts/parser/cif-chemComp.js | 5 - examples/examples/scripts/parser/cif-core.js | 14 - examples/examples/scripts/parser/cif.js | 5 - examples/examples/scripts/parser/cns.js | 12 - .../examples/scripts/parser/cube-benzene.js | 25 - examples/examples/scripts/parser/cube-big.js | 21 - .../scripts/parser/cube-bromobenzene.js | 10 - .../examples/scripts/parser/cube-protein.js | 7 - examples/examples/scripts/parser/cube.js | 12 - examples/examples/scripts/parser/dcd-large.js | 20 - examples/examples/scripts/parser/dcd.js | 20 - examples/examples/scripts/parser/dsn6.js | 10 - examples/examples/scripts/parser/dx.js | 26 - examples/examples/scripts/parser/dxbin.js | 51 - examples/examples/scripts/parser/gro-large.js | 5 - .../examples/scripts/parser/gro-trajectory.js | 13 - examples/examples/scripts/parser/gro.js | 6 - examples/examples/scripts/parser/kin.js | 47 - examples/examples/scripts/parser/map.js | 13 - .../examples/scripts/parser/mmtf-reduced.js | 2 - examples/examples/scripts/parser/mmtf.js | 6 - examples/examples/scripts/parser/mol2.js | 5 - examples/examples/scripts/parser/mrc.js | 2 - examples/examples/scripts/parser/nctraj.js | 9 - examples/examples/scripts/parser/obj.js | 11 - examples/examples/scripts/parser/pdb.js | 5 - examples/examples/scripts/parser/pdbqt.js | 9 - examples/examples/scripts/parser/ply.js | 12 - .../scripts/parser/pqr-explicit-radii.js | 16 - examples/examples/scripts/parser/pqr.js | 9 - examples/examples/scripts/parser/prmtop.js | 14 - examples/examples/scripts/parser/psf.js | 12 - .../examples/scripts/parser/sdf-models.js | 33 - examples/examples/scripts/parser/sdf.js | 5 - examples/examples/scripts/parser/top.js | 15 - examples/examples/scripts/parser/trr.js | 9 - .../examples/scripts/parser/validation.js | 18 - examples/examples/scripts/parser/xtc.js | 9 - .../examples/scripts/representation/angle.js | 16 - .../examples/scripts/representation/axes.js | 16 - .../scripts/representation/ball+stick.js | 5 - .../scripts/representation/contact.js | 71 - .../scripts/representation/dihedral.js | 21 - .../scripts/representation/distance.js | 16 - .../scripts/representation/helixorient.js | 13 - .../scripts/representation/hyperball.js | 6 - .../examples/scripts/representation/label.js | 19 - .../scripts/representation/licorice.js | 5 - .../scripts/representation/line-and-cross.js | 8 - .../examples/scripts/representation/line.js | 16 - .../representation/molecularsurface-av.js | 31 - .../representation/molecularsurface-filter.js | 43 - .../representation/molecularsurface.js | 14 - .../examples/scripts/representation/point.js | 16 - .../representation/representation-lazy.js | 6 - .../examples/scripts/representation/rocket.js | 6 - .../examples/scripts/representation/slice.js | 19 - .../scripts/representation/spacefill.js | 5 - .../examples/scripts/representation/trace.js | 5 - .../scripts/representation/tube-bfactor.js | 19 - .../scripts/representation/unitcell.js | 9 - .../examples/scripts/selection/aromatic.js | 8 - examples/examples/scripts/selection/basic.js | 8 - examples/examples/scripts/selection/bonded.js | 12 - .../examples/scripts/selection/component.js | 14 - examples/examples/scripts/selection/large.js | 27 - examples/examples/scripts/selection/ring.js | 10 - .../examples/scripts/selection/spatialHash.js | 38 - examples/examples/scripts/selection/sstruc.js | 9 - .../scripts/showcase/chlorellaVirus.js | 14 - .../scripts/showcase/electrostatic-apbs.js | 50 - .../examples/scripts/showcase/ferredoxin.js | 48 - .../examples/scripts/showcase/ferritin.js | 37 - examples/examples/scripts/showcase/gfp.js | 32 - examples/examples/scripts/showcase/hiv.js | 104 - .../examples/scripts/showcase/norovirus.js | 33 - examples/examples/scripts/showcase/qmean.js | 79 - .../examples/scripts/showcase/rhodopsin.js | 40 - .../examples/scripts/showcase/ribosome.js | 44 - examples/examples/scripts/showcase/viruses.js | 80 - examples/examples/scripts/test/1blu.js | 15 - examples/examples/scripts/test/2buk.js | 8 - examples/examples/scripts/test/alignment.js | 26 - examples/examples/scripts/test/alignment2.js | 22 - .../scripts/test/backboneTypeChange.js | 8 - examples/examples/scripts/test/concat.js | 28 - .../examples/scripts/test/dashedCylinders.js | 28 - examples/examples/scripts/test/explode.js | 56 - .../scripts/test/helixorient_issue-7.js | 12 - examples/examples/scripts/test/impostor.js | 6 - examples/examples/scripts/test/inter-bonds.js | 5 - examples/examples/scripts/test/map-shift.js | 35 - .../examples/scripts/test/molsurf-object.js | 12 - examples/examples/scripts/test/nci.js | 473 ---- examples/examples/scripts/test/orient.js | 12 - examples/examples/scripts/test/pbc.js | 9 - .../examples/scripts/test/pdbDaminoacids.js | 14 - .../scripts/test/pdbModifiedResidue.js | 12 - .../examples/scripts/test/pickingImage.js | 19 - .../examples/scripts/test/superposition.js | 18 - examples/examples/scripts/test/timing.js | 18 - examples/examples/scripts/test/xray.js | 42 - examples/examples/test.html | 34 - examples/examples/webapp.html | 64 - src/parser/itp-parser.ts | 192 -- src/stage/mouse-observer.ts | 12 - 165 files changed, 11768 deletions(-) delete mode 100644 examples/examples/annotations.html delete mode 100644 examples/examples/css/dark.css delete mode 100644 examples/examples/css/font-awesome.min.css delete mode 100644 examples/examples/css/light.css delete mode 100644 examples/examples/css/main.css delete mode 100644 examples/examples/embedded.html delete mode 100644 examples/examples/fonts/FontAwesome.otf delete mode 100644 examples/examples/fonts/fontawesome-webfont.eot delete mode 100644 examples/examples/fonts/fontawesome-webfont.svg delete mode 100644 examples/examples/fonts/fontawesome-webfont.ttf delete mode 100644 examples/examples/fonts/fontawesome-webfont.woff delete mode 100644 examples/examples/grid.html delete mode 100644 examples/examples/js/gui.js delete mode 100644 examples/examples/js/lib/colorpicker.min.js delete mode 100644 examples/examples/js/lib/signals.min.js delete mode 100644 examples/examples/js/lib/tether.min.js delete mode 100644 examples/examples/js/ui/ui.extra.js delete mode 100644 examples/examples/js/ui/ui.js delete mode 100644 examples/examples/js/ui/ui.ngl.js delete mode 100644 examples/examples/mobile.html delete mode 100644 examples/examples/parallel.html delete mode 100644 examples/examples/scripts/color/atomindex.js delete mode 100644 examples/examples/scripts/color/bfactor.js delete mode 100644 examples/examples/scripts/color/chainid.js delete mode 100644 examples/examples/scripts/color/custom.js delete mode 100644 examples/examples/scripts/color/electrostatic.js delete mode 100644 examples/examples/scripts/color/element.js delete mode 100644 examples/examples/scripts/color/modelindex.js delete mode 100644 examples/examples/scripts/color/partialcharge.js delete mode 100644 examples/examples/scripts/color/resname.js delete mode 100644 examples/examples/scripts/color/selection.js delete mode 100644 examples/examples/scripts/color/sstruc.js delete mode 100644 examples/examples/scripts/color/volume-esp.js delete mode 100644 examples/examples/scripts/color/volume.js delete mode 100644 examples/examples/scripts/component/getByName.js delete mode 100644 examples/examples/scripts/component/matrix.js delete mode 100644 examples/examples/scripts/component/shape-buffer.js delete mode 100644 examples/examples/scripts/component/shape-cat.js delete mode 100644 examples/examples/scripts/component/shape-wireframe.js delete mode 100644 examples/examples/scripts/component/shape.js delete mode 100644 examples/examples/scripts/component/structure-autoChainName.js delete mode 100644 examples/examples/scripts/component/structure-biomol.js delete mode 100644 examples/examples/scripts/component/structure-biomolSimple.js delete mode 100644 examples/examples/scripts/component/structure-bondOrders.js delete mode 100644 examples/examples/scripts/component/structure-coarseGrained.js delete mode 100644 examples/examples/scripts/component/structure-cyclic.js delete mode 100644 examples/examples/scripts/component/structure-dna.js delete mode 100644 examples/examples/scripts/component/structure-multiModel.js delete mode 100644 examples/examples/scripts/component/structure-superpose.js delete mode 100644 examples/examples/scripts/component/transform.js delete mode 100644 examples/examples/scripts/interactive/annotation.js delete mode 100644 examples/examples/scripts/interactive/crosslinking.js delete mode 100644 examples/examples/scripts/interactive/hover-tooltip.js delete mode 100644 examples/examples/scripts/interactive/interpolate.js delete mode 100644 examples/examples/scripts/interactive/ligand-viewer.js delete mode 100644 examples/examples/scripts/interactive/simple-viewer.js delete mode 100644 examples/examples/scripts/interactive/xray-viewer.js delete mode 100644 examples/examples/scripts/parser/brix.js delete mode 100644 examples/examples/scripts/parser/ccp4.js delete mode 100644 examples/examples/scripts/parser/cif-chemComp.js delete mode 100644 examples/examples/scripts/parser/cif-core.js delete mode 100644 examples/examples/scripts/parser/cif.js delete mode 100644 examples/examples/scripts/parser/cns.js delete mode 100644 examples/examples/scripts/parser/cube-benzene.js delete mode 100644 examples/examples/scripts/parser/cube-big.js delete mode 100644 examples/examples/scripts/parser/cube-bromobenzene.js delete mode 100644 examples/examples/scripts/parser/cube-protein.js delete mode 100644 examples/examples/scripts/parser/cube.js delete mode 100644 examples/examples/scripts/parser/dcd-large.js delete mode 100644 examples/examples/scripts/parser/dcd.js delete mode 100644 examples/examples/scripts/parser/dsn6.js delete mode 100644 examples/examples/scripts/parser/dx.js delete mode 100644 examples/examples/scripts/parser/dxbin.js delete mode 100644 examples/examples/scripts/parser/gro-large.js delete mode 100644 examples/examples/scripts/parser/gro-trajectory.js delete mode 100644 examples/examples/scripts/parser/gro.js delete mode 100644 examples/examples/scripts/parser/kin.js delete mode 100644 examples/examples/scripts/parser/map.js delete mode 100644 examples/examples/scripts/parser/mmtf-reduced.js delete mode 100644 examples/examples/scripts/parser/mmtf.js delete mode 100644 examples/examples/scripts/parser/mol2.js delete mode 100644 examples/examples/scripts/parser/mrc.js delete mode 100644 examples/examples/scripts/parser/nctraj.js delete mode 100644 examples/examples/scripts/parser/obj.js delete mode 100644 examples/examples/scripts/parser/pdb.js delete mode 100644 examples/examples/scripts/parser/pdbqt.js delete mode 100644 examples/examples/scripts/parser/ply.js delete mode 100644 examples/examples/scripts/parser/pqr-explicit-radii.js delete mode 100644 examples/examples/scripts/parser/pqr.js delete mode 100644 examples/examples/scripts/parser/prmtop.js delete mode 100644 examples/examples/scripts/parser/psf.js delete mode 100644 examples/examples/scripts/parser/sdf-models.js delete mode 100644 examples/examples/scripts/parser/sdf.js delete mode 100644 examples/examples/scripts/parser/top.js delete mode 100644 examples/examples/scripts/parser/trr.js delete mode 100644 examples/examples/scripts/parser/validation.js delete mode 100644 examples/examples/scripts/parser/xtc.js delete mode 100644 examples/examples/scripts/representation/angle.js delete mode 100644 examples/examples/scripts/representation/axes.js delete mode 100644 examples/examples/scripts/representation/ball+stick.js delete mode 100644 examples/examples/scripts/representation/contact.js delete mode 100644 examples/examples/scripts/representation/dihedral.js delete mode 100644 examples/examples/scripts/representation/distance.js delete mode 100644 examples/examples/scripts/representation/helixorient.js delete mode 100644 examples/examples/scripts/representation/hyperball.js delete mode 100644 examples/examples/scripts/representation/label.js delete mode 100644 examples/examples/scripts/representation/licorice.js delete mode 100644 examples/examples/scripts/representation/line-and-cross.js delete mode 100644 examples/examples/scripts/representation/line.js delete mode 100644 examples/examples/scripts/representation/molecularsurface-av.js delete mode 100644 examples/examples/scripts/representation/molecularsurface-filter.js delete mode 100644 examples/examples/scripts/representation/molecularsurface.js delete mode 100644 examples/examples/scripts/representation/point.js delete mode 100644 examples/examples/scripts/representation/representation-lazy.js delete mode 100644 examples/examples/scripts/representation/rocket.js delete mode 100644 examples/examples/scripts/representation/slice.js delete mode 100644 examples/examples/scripts/representation/spacefill.js delete mode 100644 examples/examples/scripts/representation/trace.js delete mode 100644 examples/examples/scripts/representation/tube-bfactor.js delete mode 100644 examples/examples/scripts/representation/unitcell.js delete mode 100644 examples/examples/scripts/selection/aromatic.js delete mode 100644 examples/examples/scripts/selection/basic.js delete mode 100644 examples/examples/scripts/selection/bonded.js delete mode 100644 examples/examples/scripts/selection/component.js delete mode 100644 examples/examples/scripts/selection/large.js delete mode 100644 examples/examples/scripts/selection/ring.js delete mode 100644 examples/examples/scripts/selection/spatialHash.js delete mode 100644 examples/examples/scripts/selection/sstruc.js delete mode 100644 examples/examples/scripts/showcase/chlorellaVirus.js delete mode 100644 examples/examples/scripts/showcase/electrostatic-apbs.js delete mode 100644 examples/examples/scripts/showcase/ferredoxin.js delete mode 100644 examples/examples/scripts/showcase/ferritin.js delete mode 100644 examples/examples/scripts/showcase/gfp.js delete mode 100644 examples/examples/scripts/showcase/hiv.js delete mode 100644 examples/examples/scripts/showcase/norovirus.js delete mode 100644 examples/examples/scripts/showcase/qmean.js delete mode 100644 examples/examples/scripts/showcase/rhodopsin.js delete mode 100644 examples/examples/scripts/showcase/ribosome.js delete mode 100644 examples/examples/scripts/showcase/viruses.js delete mode 100644 examples/examples/scripts/test/1blu.js delete mode 100644 examples/examples/scripts/test/2buk.js delete mode 100644 examples/examples/scripts/test/alignment.js delete mode 100644 examples/examples/scripts/test/alignment2.js delete mode 100644 examples/examples/scripts/test/backboneTypeChange.js delete mode 100644 examples/examples/scripts/test/concat.js delete mode 100644 examples/examples/scripts/test/dashedCylinders.js delete mode 100644 examples/examples/scripts/test/explode.js delete mode 100644 examples/examples/scripts/test/helixorient_issue-7.js delete mode 100644 examples/examples/scripts/test/impostor.js delete mode 100644 examples/examples/scripts/test/inter-bonds.js delete mode 100644 examples/examples/scripts/test/map-shift.js delete mode 100644 examples/examples/scripts/test/molsurf-object.js delete mode 100644 examples/examples/scripts/test/nci.js delete mode 100644 examples/examples/scripts/test/orient.js delete mode 100644 examples/examples/scripts/test/pbc.js delete mode 100644 examples/examples/scripts/test/pdbDaminoacids.js delete mode 100644 examples/examples/scripts/test/pdbModifiedResidue.js delete mode 100644 examples/examples/scripts/test/pickingImage.js delete mode 100644 examples/examples/scripts/test/superposition.js delete mode 100644 examples/examples/scripts/test/timing.js delete mode 100644 examples/examples/scripts/test/xray.js delete mode 100644 examples/examples/test.html delete mode 100644 examples/examples/webapp.html delete mode 100644 src/parser/itp-parser.ts diff --git a/examples/examples/annotations.html b/examples/examples/annotations.html deleted file mode 100644 index aa0c4425f..000000000 --- a/examples/examples/annotations.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - NGL - test - - - - - - - -
- - \ No newline at end of file diff --git a/examples/examples/css/dark.css b/examples/examples/css/dark.css deleted file mode 100644 index f79e854c0..000000000 --- a/examples/examples/css/dark.css +++ /dev/null @@ -1,69 +0,0 @@ - -/* text color */ - -* { - color: #B8B8B8; -} - -input, -textarea, -button, -select, -option { - color: #111111; -} - -input[type=range]:focus:after { - color: #B8B8B8; -} - -a{ - color: #719eff; -} - -input.Number, input.File { - color: #A1B56C; -} - - -/* background color */ - -.OverlayPanel, -#menubar, -#menubar .menu .options, -#sidebar, -#toolbar -{ - background-color: #1C1F26; -} - - -/* border color */ - -.OverlayPanel, -#menubar .menu .options hr, -#sidebar > .Panel, -#sidebar > .Content > .Panel { - border-color: #444444; -} - - -/* special */ - -#menubar .menu .options .option:hover, -.option:hover > .Icon, -.option:hover > .Text { - color: #181818; - background-color: #7CAFC2; -} - -.highlight, -.highlight > .Icon, -.highlight > .Text { - color: #181818; - background-color: #7CAFC2; -} - -.EllipsisMultilineText:after { - background: linear-gradient(to right, rgba(0, 0, 0, 0), #1C1F26 50%, #1C1F26); -} diff --git a/examples/examples/css/font-awesome.min.css b/examples/examples/css/font-awesome.min.css deleted file mode 100644 index 3d920fc87..000000000 --- a/examples/examples/css/font-awesome.min.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! - * Font Awesome 4.1.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.1.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.1.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.1.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.1.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-square:before,.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"} \ No newline at end of file diff --git a/examples/examples/css/light.css b/examples/examples/css/light.css deleted file mode 100644 index d08e750d6..000000000 --- a/examples/examples/css/light.css +++ /dev/null @@ -1,69 +0,0 @@ - -/* text color */ - -* { - color: #555555; -} - -input, -textarea, -button, -select, -option { - color: #111111; -} - -input[type=range]:focus:after { - color: #555555; -} - -a{ - color: #1956d8; -} - -input.Number, input.File { - color: #79952e; -} - - -/* background color */ - -.OverlayPanel, -#menubar, -#menubar .menu .options, -#sidebar, -#toolbar -{ - background-color: #e1e4eb; -} - - -/* border color */ - -.OverlayPanel, -#menubar .menu .options hr, -#sidebar > .Panel, -#sidebar > .Content > .Panel { - border-color: #cccccc; -} - - -/* special */ - -#menubar .menu .options .option:hover, -.option:hover > .Icon, -.option:hover > .Text { - color: #D8D8D8; - background-color: #345a69; -} - -.highlight, -.highlight > .Icon, -.highlight > .Text { - color: #D8D8D8; - background-color: #345a69; -} - -.EllipsisMultilineText:after { - background: linear-gradient(to right, rgba(255, 255, 255, 0), #e1e4eb 50%, #e1e4eb); -} diff --git a/examples/examples/css/main.css b/examples/examples/css/main.css deleted file mode 100644 index fa4e3309f..000000000 --- a/examples/examples/css/main.css +++ /dev/null @@ -1,454 +0,0 @@ - -* { - vertical-align: middle; -} - -/* Webkit micro scrollbars */ - -::-webkit-scrollbar { - width:9px; - height:9px; -} - -::-webkit-scrollbar-track { - -webkit-border-radius:5px; - border-radius:5px; - background:rgba(140,140,140,0.1); -} - -::-webkit-scrollbar-thumb { - -webkit-border-radius:5px; - border-radius:5px; - background:rgba(140,140,140,0.2); -} - -::-webkit-scrollbar-thumb:hover { - background:rgba(140,140,140,0.4); -} - -::-webkit-scrollbar-thumb:window-inactive { - background:rgba(140,140,140,0.5); -} - -/* elmement */ - -body { - font-family: Arial, sans-serif; - font-size: 14px; - margin: 0; - overflow: hidden; -} - -hr { - border: 0px; - border-top: 1px solid #ccc; -} - -button { - position: relative; - margin-left: 0px; -} - -select { - margin-left: 1px; -} - -textarea { - white-space: pre; - word-wrap: normal; -} - - textarea.success { - border-color: #8b8 !important; - } - - textarea.fail { - border-color: #f00 !important; - background-color: rgba(255,0,0,0.05); - } - -textarea, input { outline: none; } /* osx */ - -input.Number { - font-size: 12px; /** TODO: Use of !imporant is not ideal **/ - background-color: transparent!important; /* For now this is a quick fix a rendering issue due to inherited background */ - border: 1px solid transparent; - padding: 2px; - cursor: col-resize; -} - -input.File { - border: 0px solid !important; - padding: 0px !important; -} - -input[type=range]:focus:after { - position: absolute; - transform: translate(-100%,-50% ); - content: attr(value); - font-size: 12px; -} - -/* class */ - -.deleteInfo:after { - position: absolute; - transform: translate(-50%,-250% ); - content: "double-click to delete"; - font-size: 10px; - display: block; -} - -.Panel { - - -moz-user-select: none; - -webkit-user-select: none; - -ms-user-select: none; - - /* No support for these yet */ - -o-user-select: none; - user-select: none; -} - -.OverlayPanel { - z-index: 10; - position: absolute; - padding: 10px; - overflow: auto; - border: 1px solid; -} - -.OverlayPanel:focus { - z-index: 20; -} - -.Text { - cursor: default; -} - -.FancySelect { - padding: 0; - cursor: default; - overflow: auto; - outline: none; -} - - .FancySelect .option { - padding: 4px; - white-space: nowrap; - } - -.CollapsiblePanel .CollapsiblePanelButton { - float: left; - margin-right: 6px; - width: 0px; - height: 0px; - border: 6px solid transparent; -} - -.CollapsiblePanel.collapsed > .CollapsiblePanelButton { - margin-top: 2px; - border-left-color: #555; -} - -.CollapsiblePanel:not(.collapsed) > .CollapsiblePanelButton { - margin-top: 6px; - border-top-color: #555; -} - -.CollapsiblePanel.collapsed .CollapsibleContent { - display: none; -} - -.CollapsiblePanel:not(.collapsed) > .CollapsibleContent { - clear: both; -} - -/* http://www.brianchu.com/blog/2013/11/02/creating-an-auto-growing-text-input/ */ - -.AdaptiveTextAreaContainer { - position: relative; - display: inline-block; - margin-top: 2px; - margin-bottom: 2px; -} - -.AdaptiveTextArea, .AdaptiveTextAreaSize { - min-height: 21px; - /* need to manually set font and font size */ - font-family: Arial, sans-serif; - font-size: 13px; - box-sizing: border-box; - padding: 2px; - border: 1px solid #ccc; - - overflow: hidden; - width: 100%; -} - -.AdaptiveTextArea { - height: 100%; - position: absolute; - resize: none; - - /* - "pre" or "preline" or "normal" fixes Chrome issue where - whitespace at end of lines does not trigger a line break. - However, it causes the text to exhibit the behavior seen with - "pre" that is described below. - */ - white-space: normal; - word-wrap: break-word; - overflow-wrap: break-word; -} - -.AdaptiveTextAreaSize { - visibility: hidden; - - /* - Pre-wrap: preserve spacing and newlines, but wrap text. - Pre: preserve spacing and newlines but don't wrap text. - - "pre" does not wrap well on Firefox, even with word-wrap:break-word. - "pre" on Chrome works with word-wrap, but exhibits different behavior: - Instead of entire words being moved to the next line for wrapping, - the browser will cut words in the middle for wrapping. - "pre-line" has Firefox issues - */ - white-space: pre-wrap; - /* Required for wrapping lines in Webkit, - but not necessary in Firefox if you have white-space wrapping - (pre-wrap, normal, pre-line) already set */ - word-wrap: break-word; - overflow-wrap: break-word; -} - -/* FlexiColorPicker */ - -.picker-wrapper, -.slide-wrapper { - position: relative; - float: left; -} - -.picker-indicator, -.slide-indicator { - position: absolute; - left: 0; - top: 0; - pointer-events: none; -} - -.picker, -.slide { - cursor: crosshair; - float: left; -} - -.slide-wrapper { - margin-left: 10px; -} - -.picker-indicator { - width: 5px; - height: 5px; - border: 2px solid darkblue; - -moz-border-radius: 4px; - -o-border-radius: 4px; - -webkit-border-radius: 4px; - border-radius: 4px; - opacity: .5; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; - filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50); - filter: alpha(opacity=50); - background-color: white; -} - -.slide-indicator { - width: 100%; - height: 10px; - left: -4px; - opacity: .6; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"; - filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=60); - filter: alpha(opacity=60); - border: 4px solid lightblue; - -moz-border-radius: 4px; - -o-border-radius: 4px; - -webkit-border-radius: 4px; - border-radius: 4px; - background-color: white; -} - -/* http://www.mobify.com/blog/multiline-ellipsis-in-pure-css/ */ - -.EllipsisMultilineText { - overflow: hidden; - max-height: 2.6em; - line-height: 1.3em; -} - -.EllipsisMultilineText:before { - content:""; - float: left; - width: 5px; - max-height: 2.6em; -} - -.EllipsisMultilineText > *:first-child { - float: right; - width: 100%; - margin-top: 0px; - margin-bottom: 0px; - margin-left: -5px; - word-wrap: break-word; -} - -.EllipsisMultilineText:after { - content: "\02026"; - - box-sizing: content-box; - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - - float: right; position: relative; - top: 1.3em; left: 100%; - width: 3em; margin-left: -3em; - padding-right: 5px; - - text-align: right; -} - -/* resize */ - -.ResizeLeft, .ResizeLeft:hover { - position: relative; - float: left; - height: 100%; - width: 10px; -} - -.ResizeLeft:hover{ - cursor: col-resize; -} - -/* virtual list */ - -.VirtualListRow { - position: absolute; - overflow: hidden; - white-space: nowrap; - display: inline-block; -} - -.VirtualListRow > .Text { - cursor: inherit; -} - -/* id */ - -#viewport { - position: absolute; - top: 32px; - left: 0px; - right: 300px; - bottom: 32px; -} - -#menubar { - position: absolute; - width: 100%; - height: 32px; - padding: 0px; - margin: 0px; - z-index: 100; - top: 0px; - left: 0px; -} - - #menubar .menu { - float: left; - cursor: pointer; - position: relative; - } - - #menubar .menu .title { - margin: 0px; - padding: 8px; - } - - #menubar .menu .options { - display: none; - padding: 5px 0px; - width: 140px; - position: absolute; - top: 32px; - } - - #menubar .menu:hover .options { - display: block; - max-height: 600px; - overflow: auto; - } - - #menubar .menu .options .option { - background-color: transparent; - padding: 5px 10px; - margin: 0px !important; - } - -#sidebar { - position: absolute; - right: 0px; - top: 32px; - bottom: 0px; - width: 300px; - overflow: hidden; -} - - #sidebar .Panel { - margin-bottom: 10px; - } - - #sidebar .Panel.collapsed { - margin-bottom: 0px; - } - - #sidebar .CollapsibleContent { - margin-top: 10px; - } - - #sidebar > .Panel { - padding: 10px; - border-top: 1px solid; - } - - #sidebar > .Content > .Panel { - padding: 10px; - border-top: 1px solid; - } - - #sidebar .Content { - top: 40px; - bottom: 0px; - position: absolute; - overflow: auto; - right: 0px; - width: 100%; - } - -#toolbar { - position: absolute; - left: 0px; - right: 300px; - bottom: 0px; - height: 32px; -} - - #toolbar .Panel { - padding: 6px; - } - - #toolbar button { - margin-right: 6px; - } diff --git a/examples/examples/embedded.html b/examples/examples/embedded.html deleted file mode 100644 index 3fcbfceb3..000000000 --- a/examples/examples/embedded.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - NGL - embedded - - - - - - -
- - diff --git a/examples/examples/fonts/FontAwesome.otf b/examples/examples/fonts/FontAwesome.otf deleted file mode 100644 index 3461e3fce6a37f2321ecbe64707f04c0a4f05424..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75188 zcmd42cYG5^*C@QQyeoNEmI+v3OJ1!hp?BN#Bql&0F(rUQ=*C61jEjsU_uhM#yN!)a zZ=nSOfy5~U0x2Yzbn+xmdPp$|WF(Ia_sq&BJV=l2St!J@u6Ld}hLIigG(oNmSNVYp2bu*`8&mCT(g%JrKs|W6VjPjD7@?@<57`EsF_Gij(~7S;$jX z2uy5njLz_R|~-giuu0_{g+f+ve88OQ{Hz6>Y}qGm4HH8LdoEP_Ir~wHA13xKq37E z1Q7#%ImkKEQfdVC%s|@tAvjG9rGf|G%tLS)wVE;wz~z*JdUGJ{Lb24ffiy>{sLuw{ zN=i%p4&x(nc7ggcB(4K#2{l|&I*@jvl#*QoX(=^T^1?vc`5_#d8Y8(m0B0V8%cxE# z$pBnVc{p_qq+KX?r%B0{5Tf&5n`|=c zVocso$A%h=aRy_sSr<0ddtr36w}@);HtI||V*&u5GQ^q}ChAOv7#*33dEO5J<`I%J z*XfL=NJFf*@6;JnrxS?Jv(dU>lMZNv>x|xJgST0)^ZvUTCS9nR;D;OFCALM<4|cS0 zYNX*m0;fd-nOKu<8nuWrP;pc;Wuzjh2ue?xfq7<9)2SJhFQgVyVemeL(m{GHV42{( zj*5ZUn|hjxr9$DY5z3R_VDViTHB~GZO+`ceH&s%?2xUzWj8p>r63nNdWGs|hNF|Ez z3_x2)t$`3h#RG+4z;(3FM9l*V{~4dWakP0RwGPS}p_WLIvN!Z%D)eP4^k@*r2UcJ- zU?=@*H?{x2(58Ba^p5QH?|rs+TW>_~_TISOtlp~Lj^1Ov-M!a( zzv}J1P2C=H+Z$+4xIO*0|LtdQZ@V3LJL`7U?T*{WZg=0lcKa(r`~KGyb$|2y)%O?P zpZ?_!U)FuOW{B$$#SnIg%Mkex*jk1-50MUW8X_4&x!rfW>vqTOPq#nZZoBom{jU7N z?Kihy-F|Vq<@U4NPi{ZD{owY!+jnl?x_#sJZ|;=H59|LA1MdHSc=vyM#lTJ^gTau`vLeC!n{ysFfXP_Uc`a;;df9b8Q`%5CI-q;j?f_Z z08@+f2t13LIfyd|dpIWbJ7SE2M+X6Y`2Iv zkp55o6=8%9;E*zdF@cM1gm+?lAU^<05&JWMOK=9?GfrY#nxQ=#37!98@E7s2C_kX( zC)VL8>pEDTzy|wG(u4WIx(CZZyip8U549cAFn<07M;srB30*Ni03+$ax};f-cVgcG z?mU=>^dM|7CT$V}dFOaPnef&?TC8tyti(D1AN0WcgLMzq`5)sfN=5Jn`%Q2L%ZV|e zl|>C1nDg+#cYyEwFueh|8;M1@qnrlv{tx2;EpI}L@Bj%;S(HBnvCo4r5Z3J3VAh|L z<;C|91Fq}f+8ik7{a@>YGGgBWt|0H6vm9+D_>zG%!GU*vgSez_v3`gN?0**q@gSZe z&4DsfsLMf%#B&~$%c2BmvjBC70pNldvK)OGz|)9*7$^_8{)72JI)izrZzX|2bz&g6 z5X63xu^GT)2Fno{M$)8hgZ%>hi3CQMO{9n`r5)Xz4^*h=``X=^^&>Ji>7z6GQLVJL| z_aKddx*yOSg#T~iaf59p@jw_#VuBCxViH3?=0bWXsoR0$7|#Km$Kk!l!}JNx|I;6t zQ24u_Le9kh{ZB$TOd^pe9yTF>YR?YaZFd!x{0fp_1!PlmxoWQIAlbaCRI;O$No?ms&tQPAvhI zcLfzlZKi@i0oH?3y#tirbSj%Fr|PH{s)IU29j9KRy5UrMnfj3Wg8G5#rT(J&;SlaD zkxPb1R1%Fukc^g0koZa-mn@S6N`fTOk~m4Kq)<{PX_a(J4ogl*PD{>7UX{Elxh%OM z`M2a}$#0TBB}j75iFF$8q;VSOd9(^983P8*!UoeWONP6bYtPEAf-PDhGoA5e9%B|W&ob+o%}g+} zor!0%nS7>*zlX3A#CmdZBB z^s;1GuB<{3O7?^7SJ@vjyIdjH$RCx@kk69Omp?9FB3~hY zP97?ck{jen@yA4hRgPR6M?4L6qa z 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�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 DgjuED diff --git a/examples/examples/fonts/fontawesome-webfont.eot b/examples/examples/fonts/fontawesome-webfont.eot deleted file mode 100644 index 6cfd56609567bc9db55186415c694d1d32808fc2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72449 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
U~M!&>g0b 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 diff --git a/examples/examples/fonts/fontawesome-webfont.svg b/examples/examples/fonts/fontawesome-webfont.svg deleted file mode 100644 index a9f846950..000000000 --- a/examples/examples/fonts/fontawesome-webfont.svg +++ /dev/null @@ -1,504 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/examples/examples/fonts/fontawesome-webfont.ttf b/examples/examples/fonts/fontawesome-webfont.ttf deleted file mode 100644 index 5cd6cff6d6f6cf438a882e366420dbcc5dddd3f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141564 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ƓCICn66&u!PHl6pn& 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%0D%8GQ!Ai?6y^fVUY%4hi>cI9O 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
KT23~?3Dw&p)A=062yj$!;@;Sv13 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 - - - NGL - grid - - - - - - -

Grid

- - diff --git a/examples/examples/js/gui.js b/examples/examples/js/gui.js deleted file mode 100644 index fca61e7b7..000000000 --- a/examples/examples/js/gui.js +++ /dev/null @@ -1,2394 +0,0 @@ -/** - * @file Gui - * @author Alexander Rose - */ - -HTMLElement.prototype.getBoundingClientRect = (function () { - // workaround for ie11 behavior with disconnected dom nodes - - var _getBoundingClientRect = HTMLElement.prototype.getBoundingClientRect - - return function getBoundingClientRect () { - try { - return _getBoundingClientRect.apply(this, arguments) - } catch (e) { - return { - top: 0, - left: 0, - width: this.width, - height: this.height - } - } - } -}()) - -NGL.Widget = function () { - -} - -NGL.Widget.prototype = { - constructor: NGL.Widget -} - -NGL.createParameterInput = function (p, v) { - if (!p) return - - var value = v === undefined ? p.value : v - var input - - if (p.type === 'number') { - input = new UI.Number(0) - .setRange(p.min, p.max) - .setPrecision(p.precision) - .setValue(parseFloat(value)) - } else if (p.type === 'integer') { - input = new UI.Integer(parseInt(value)) - .setRange(p.min, p.max) - } else if (p.type === 'range') { - input = new UI.Range(p.min, p.max, value, p.step) - .setValue(parseFloat(value)) - } else if (p.type === 'boolean') { - input = new UI.Checkbox(value) - } else if (p.type === 'text') { - input = new UI.Input(value) - } else if (p.type === 'select') { - input = new UI.Select() - .setWidth('') - .setOptions(p.options) - .setValue(value) - } else if (p.type === 'color') { - input = new UI.ColorPopupMenu(p.label) - .setValue(value) - } else if (p.type === 'vector3') { - input = new UI.Vector3(value) - .setPrecision(p.precision) - } else if (p.type === 'hidden') { - - // nothing to display - - } else { - console.warn( - 'NGL.createParameterInput: unknown parameter type ' + - "'" + p.type + "'" - ) - } - - return input -} - -/// ///////////// -// Preferences - -NGL.Preferences = function (id, defaultParams) { - this.signals = { - keyChanged: new signals.Signal() - } - - this.id = id || 'ngl-gui' - var dp = Object.assign({}, defaultParams) - - this.storage = { - impostor: true, - quality: 'auto', - sampleLevel: 0, - theme: 'dark', - backgroundColor: 'black', - overview: true, - rotateSpeed: 2.0, - zoomSpeed: 1.2, - panSpeed: 0.8, - clipNear: 0, - clipFar: 100, - clipDist: 10, - fogNear: 50, - fogFar: 100, - cameraFov: 40, - cameraType: 'perspective', - lightColor: 0xdddddd, - lightIntensity: 1.0, - ambientColor: 0xdddddd, - ambientIntensity: 0.2, - hoverTimeout: 0 - } - - // overwrite default values with params - for (var key in this.storage) { - if (dp[ key ] !== undefined) { - this.storage[ key ] = dp[ key ] - } - } - - try { - if (window.localStorage[ this.id ] === undefined) { - window.localStorage[ this.id ] = JSON.stringify(this.storage) - } else { - var data = JSON.parse(window.localStorage[ this.id ]) - for (var key in data) { - this.storage[ key ] = data[ key ] - } - } - } catch (e) { - NGL.error('localStorage not accessible/available') - } -} - -NGL.Preferences.prototype = { - - constructor: NGL.Preferences, - - getKey: function (key) { - return this.storage[ key ] - }, - - setKey: function (key, value) { - this.storage[ key ] = value - - try { - window.localStorage[ this.id ] = JSON.stringify(this.storage) - this.signals.keyChanged.dispatch(key, value) - } catch (e) { - // Webkit === 22 / Firefox === 1014 - if (e.code === 22 || e.code === 1014) { - NGL.error('localStorage full') - } else { - NGL.error('localStorage not accessible/available', e) - } - } - }, - - clear: function () { - try { - delete window.localStorage[ this.id ] - } catch (e) { - NGL.error('localStorage not accessible/available') - } - } - -} - -// Stage - -NGL.StageWidget = function (stage) { - var viewport = new NGL.ViewportWidget(stage).setId('viewport') - document.body.appendChild(viewport.dom) - - // ensure initial focus on viewer canvas for key-stroke listening - stage.viewer.renderer.domElement.focus() - - // - - var preferences = new NGL.Preferences('ngl-stage-widget') - - var pp = {} - for (var name in preferences.storage) { - pp[ name ] = preferences.getKey(name) - } - stage.setParameters(pp) - - preferences.signals.keyChanged.add(function (key, value) { - var sp = {} - sp[ key ] = value - stage.setParameters(sp) - if (key === 'theme') { - setTheme(value) - } - }, this) - - // - - var cssLinkElement = document.createElement('link') - cssLinkElement.rel = 'stylesheet' - cssLinkElement.id = 'theme' - - function setTheme (value) { - var cssPath, bgColor - if (value === 'light') { - cssPath = NGL.cssDirectory + 'light.css' - bgColor = 'white' - } else { - cssPath = NGL.cssDirectory + 'dark.css' - bgColor = 'black' - } - cssLinkElement.href = cssPath - stage.setParameters({ backgroundColor: bgColor }) - } - - setTheme(preferences.getKey('theme')) - document.head.appendChild(cssLinkElement) - - // - - var toolbar = new NGL.ToolbarWidget(stage).setId('toolbar') - document.body.appendChild(toolbar.dom) - - var menubar = new NGL.MenubarWidget(stage, preferences).setId('menubar') - document.body.appendChild(menubar.dom) - - var sidebar = new NGL.SidebarWidget(stage).setId('sidebar') - document.body.appendChild(sidebar.dom) - - // - - document.body.style.touchAction = 'none' - - // - - stage.handleResize() - // FIXME hack for ie11 - setTimeout(function () { stage.handleResize() }, 500) - - // - - var doResizeLeft = false - var movedResizeLeft = false - var minResizeLeft = false - - var handleResizeLeft = function (clientX) { - if (clientX >= 50 && clientX <= window.innerWidth - 10) { - sidebar.setWidth(window.innerWidth - clientX + 'px') - viewport.setWidth(clientX + 'px') - toolbar.setWidth(clientX + 'px') - stage.handleResize() - } - var sidebarWidth = sidebar.dom.getBoundingClientRect().width - if (clientX === undefined) { - var mainWidth = window.innerWidth - sidebarWidth - viewport.setWidth(mainWidth + 'px') - toolbar.setWidth(mainWidth + 'px') - stage.handleResize() - } - if (sidebarWidth <= 10) { - minResizeLeft = true - } else { - minResizeLeft = false - } - } - handleResizeLeft = NGL.throttle( - handleResizeLeft, 50, { leading: true, trailing: true } - ) - - var resizeLeft = new UI.Panel() - .setClass('ResizeLeft') - .onMouseDown(function () { - doResizeLeft = true - movedResizeLeft = false - }) - .onClick(function () { - if (minResizeLeft) { - handleResizeLeft(window.innerWidth - 300) - } else if (!doResizeLeft && !movedResizeLeft) { - handleResizeLeft(window.innerWidth - 10) - } - }) - - sidebar.add(resizeLeft) - - window.addEventListener( - 'mousemove', function (event) { - if (doResizeLeft) { - document.body.style.cursor = 'col-resize' - movedResizeLeft = true - handleResizeLeft(event.clientX) - } - }, false - ) - - window.addEventListener( - 'mouseup', function (event) { - doResizeLeft = false - document.body.style.cursor = '' - }, false - ) - - window.addEventListener( - 'resize', function (event) { - handleResizeLeft() - }, false - ) - - // - - document.addEventListener('dragover', function (e) { - e.stopPropagation() - e.preventDefault() - e.dataTransfer.dropEffect = 'none' - }, false) - - document.addEventListener('drop', function (e) { - e.stopPropagation() - e.preventDefault() - }, false) - - this.viewport = viewport - this.toolbar = toolbar - this.menubar = menubar - this.sidebar = sidebar - - return this -} - -// Viewport - -NGL.ViewportWidget = function (stage) { - var viewer = stage.viewer - var renderer = viewer.renderer - - var container = new UI.Panel() - container.dom = viewer.container - container.setPosition('absolute') - - var fileTypesOpen = NGL.flatten([ - NGL.ParserRegistry.getStructureExtensions(), - NGL.ParserRegistry.getVolumeExtensions(), - NGL.ParserRegistry.getSurfaceExtensions(), - NGL.DecompressorRegistry.names - ]) - - // event handlers - - container.dom.addEventListener('dragover', function (e) { - e.stopPropagation() - e.preventDefault() - e.dataTransfer.dropEffect = 'copy' - }, false) - - container.dom.addEventListener('drop', function (e) { - e.stopPropagation() - e.preventDefault() - - var fn = function (file, callback) { - var ext = file.name.split('.').pop().toLowerCase() - if (NGL.ScriptExtensions.includes(ext)) { - stage.loadScript(file).then(callback) - } else if (fileTypesOpen.includes(ext)) { - stage.loadFile(file, { defaultRepresentation: true }).then(callback) - } else { - console.error('unknown filetype: ' + ext) - callback() - } - } - var queue = new NGL.Queue(fn, e.dataTransfer.files) - }, false) - - return container -} - -// Toolbar - -NGL.ToolbarWidget = function (stage) { - var container = new UI.Panel() - - var messageText = new UI.Text() - var messagePanel = new UI.Panel() - .setDisplay('inline') - .setFloat('left') - .add(messageText) - - var statsText = new UI.Text() - var statsPanel = new UI.Panel() - .setDisplay('inline') - .setFloat('right') - .add(statsText) - - stage.signals.clicked.add(function (pickingProxy) { - messageText.setValue(pickingProxy ? pickingProxy.getLabel() : 'nothing') - }) - - stage.viewer.stats.signals.updated.add(function () { - if (NGL.Debug) { - statsText.setValue( - stage.viewer.stats.lastDuration.toFixed(2) + ' ms | ' + - stage.viewer.stats.lastFps + ' fps' - ) - } else { - statsText.setValue('') - } - }) - - container.add(messagePanel, statsPanel) - - return container -} - -// Menubar - -NGL.MenubarWidget = function (stage, preferences) { - var container = new UI.Panel() - - container.add(new NGL.MenubarFileWidget(stage)) - container.add(new NGL.MenubarViewWidget(stage, preferences)) - if (NGL.examplesListUrl && NGL.examplesScriptUrl) { - container.add(new NGL.MenubarExamplesWidget(stage)) - } - container.add(new NGL.MenubarHelpWidget(stage, preferences)) - - container.add( - new UI.Panel().setClass('menu').setFloat('right').add( - new UI.Text('NGL Viewer ' + NGL.Version).setClass('title') - ) - ) - - return container -} - -NGL.MenubarFileWidget = function (stage) { - var fileTypesOpen = NGL.flatten([ - NGL.ParserRegistry.getStructureExtensions(), - NGL.ParserRegistry.getVolumeExtensions(), - NGL.ParserRegistry.getSurfaceExtensions(), - NGL.DecompressorRegistry.names, - NGL.ScriptExtensions - ]) - - function fileInputOnChange (e) { - var fn = function (file, callback) { - var ext = file.name.split('.').pop().toLowerCase() - if (NGL.ScriptExtensions.includes(ext)) { - stage.loadScript(file).then(callback) - } else if (fileTypesOpen.includes(ext)) { - stage.loadFile(file, { defaultRepresentation: true }).then(callback) - } else { - console.error('unknown filetype: ' + ext) - callback() - } - } - var queue = new NGL.Queue(fn, e.target.files) - } - - var fileInput = document.createElement('input') - fileInput.type = 'file' - fileInput.multiple = true - fileInput.style.display = 'none' - fileInput.accept = '.' + fileTypesOpen.join(',.') - fileInput.addEventListener('change', fileInputOnChange, false) - - // export image - - var exportImageWidget = new NGL.ExportImageWidget(stage) - .setDisplay('none') - .attach() - - // event handlers - - function onOpenOptionClick () { - fileInput.click() - } - - function onImportOptionClick () { - var dirWidget - function onListingClick (info) { - var ext = info.path.split('.').pop().toLowerCase() - if (NGL.ScriptExtensions.includes(ext)) { - stage.loadScript(NGL.ListingDatasource.getUrl(info.path)) - dirWidget.dispose() - } else if (fileTypesOpen.includes(ext)) { - stage.loadFile(NGL.ListingDatasource.getUrl(info.path), { - defaultRepresentation: true - }) - dirWidget.dispose() - } else { - console.error('unknown filetype: ' + ext) - } - } - - dirWidget = new NGL.DirectoryListingWidget( - NGL.ListingDatasource, stage, 'Import file', - fileTypesOpen, onListingClick - ) - - dirWidget - .setOpacity('0.9') - .setLeft('50px') - .setTop('80px') - .attach() - } - - function onExportImageOptionClick () { - exportImageWidget - .setOpacity('0.9') - .setLeft('50px') - .setTop('80px') - .setDisplay('block') - } - - function onScreenshotOptionClick () { - stage.makeImage({ - factor: 1, - antialias: true, - trim: false, - transparent: false - }).then(function (blob) { - NGL.download(blob, 'screenshot.png') - }) - } - - function onPdbInputKeyDown (e) { - if (e.keyCode === 13) { - stage.loadFile('rcsb://' + e.target.value.trim(), { - defaultRepresentation: true - }) - e.target.value = '' - } - } - - function onAsTrajectoryChange (e) { - stage.defaultFileParams.asTrajectory = e.target.checked - } - - function onFirstModelOnlyChange (e) { - stage.defaultFileParams.firstModelOnly = e.target.checked - } - - function onCAlphaOnlyChange (e) { - stage.defaultFileParams.cAlphaOnly = e.target.checked - } - - // configure menu contents - - var createOption = UI.MenubarHelper.createOption - var createInput = UI.MenubarHelper.createInput - var createCheckbox = UI.MenubarHelper.createCheckbox - var createDivider = UI.MenubarHelper.createDivider - - var menuConfig = [ - createOption('Open...', onOpenOptionClick), - createInput('PDB', onPdbInputKeyDown), - createCheckbox('asTrajectory', false, onAsTrajectoryChange), - createCheckbox('firstModelOnly', false, onFirstModelOnlyChange), - createCheckbox('cAlphaOnly', false, onCAlphaOnlyChange), - createDivider(), - createOption('Screenshot', onScreenshotOptionClick, 'camera'), - createOption('Export image...', onExportImageOptionClick) - ] - - if (NGL.ListingDatasource) { - menuConfig.splice( - 1, 0, createOption('Import...', onImportOptionClick) - ) - } - - var optionsPanel = UI.MenubarHelper.createOptionsPanel(menuConfig) - optionsPanel.dom.appendChild(fileInput) - - return UI.MenubarHelper.createMenuContainer('File', optionsPanel) -} - -NGL.MenubarViewWidget = function (stage, preferences) { - // event handlers - - function onLightThemeOptionClick () { - preferences.setKey('theme', 'light') - } - - function onDarkThemeOptionClick () { - preferences.setKey('theme', 'dark') - } - - function onPerspectiveCameraOptionClick () { - stage.setParameters({ cameraType: 'perspective' }) - } - - function onOrthographicCameraOptionClick () { - stage.setParameters({ cameraType: 'orthographic' }) - } - - function onStereoCameraOptionClick () { - stage.setParameters({ cameraType: 'stereo' }) - } - - function onFullScreenOptionClick () { - stage.toggleFullscreen(document.body) - } - - function onCenterOptionClick () { - stage.autoView(1000) - } - - function onToggleSpinClick () { - stage.toggleSpin() - } - - function onToggleRockClick () { - stage.toggleRock() - } - - function onGetOrientationClick () { - window.prompt( - 'Get orientation', - JSON.stringify( - stage.viewerControls.getOrientation().toArray(), - function (k, v) { - return v.toFixed ? Number(v.toFixed(2)) : v - } - ) - ) - } - - function onSetOrientationClick () { - stage.viewerControls.orient( - JSON.parse(window.prompt('Set orientation')) - ) - } - - stage.signals.fullscreenChanged.add(function (isFullscreen) { - var icon = menuConfig[ 6 ].children[ 0 ] - if (isFullscreen) { - icon.switchClass('compress', 'expand') - } else { - icon.switchClass('expand', 'compress') - } - }) - - // configure menu contents - - var createOption = UI.MenubarHelper.createOption - var createDivider = UI.MenubarHelper.createDivider - - var menuConfig = [ - createOption('Light theme', onLightThemeOptionClick), - createOption('Dark theme', onDarkThemeOptionClick), - createDivider(), - createOption('Perspective', onPerspectiveCameraOptionClick), - createOption('Orthographic', onOrthographicCameraOptionClick), - createOption('Stereo', onStereoCameraOptionClick), - createDivider(), - createOption('Full screen', onFullScreenOptionClick, 'expand'), - createOption('Center', onCenterOptionClick, 'bullseye'), - createDivider(), - createOption('Toggle spin', onToggleSpinClick), - createOption('Toggle rock', onToggleRockClick), - createDivider(), - createOption('Get orientation', onGetOrientationClick), - createOption('Set orientation', onSetOrientationClick) - ] - - var optionsPanel = UI.MenubarHelper.createOptionsPanel(menuConfig) - - return UI.MenubarHelper.createMenuContainer('View', optionsPanel) -} - -NGL.MenubarExamplesWidget = function (stage) { - // configure menu contents - - var createOption = UI.MenubarHelper.createOption - var optionsPanel = UI.MenubarHelper.createOptionsPanel([]) - optionsPanel.setWidth('300px') - - var xhr = new XMLHttpRequest() - xhr.open('GET', NGL.examplesListUrl) - xhr.responseType = 'json' - xhr.onload = function (e) { - var response = this.response - if (typeof response === 'string') { - // for ie11 - response = JSON.parse(response) - } - response.sort().forEach(function (name) { - var option = createOption(name, function () { - stage.loadScript(NGL.examplesScriptUrl + name + '.js') - }) - optionsPanel.add(option) - }) - } - xhr.send() - - return UI.MenubarHelper.createMenuContainer('Examples', optionsPanel) -} - -NGL.MenubarHelpWidget = function (stage, preferences) { - // event handlers - - function onOverviewOptionClick () { - overviewWidget - .setOpacity('0.9') - .setDisplay('block') - .setWidgetPosition(50, 80) - } - - function onDocOptionClick () { - window.open(NGL.documentationUrl, '_blank') - } - - function onDebugOnClick () { - NGL.setDebug(true) - stage.viewer.updateHelper() - stage.viewer.requestRender() - } - - function onDebugOffClick () { - NGL.setDebug(false) - stage.viewer.updateHelper() - stage.viewer.requestRender() - } - - function onPreferencesOptionClick () { - preferencesWidget - .setOpacity('0.9') - .setDisplay('block') - .setWidgetPosition(50, 80) - } - - // export image - - var preferencesWidget = new NGL.PreferencesWidget(stage, preferences) - .setDisplay('none') - .attach() - - // overview - - var overviewWidget = new NGL.OverviewWidget(stage, preferences) - .setDisplay('none') - .attach() - - if (preferences.getKey('overview')) { - onOverviewOptionClick() - } - - // configure menu contents - - var createOption = UI.MenubarHelper.createOption - var createDivider = UI.MenubarHelper.createDivider - - var menuConfig = [ - createOption('Overview', onOverviewOptionClick), - createOption('Documentation', onDocOptionClick), - createDivider(), - createOption('Debug on', onDebugOnClick), - createOption('Debug off', onDebugOffClick), - createDivider(), - createOption('Preferences', onPreferencesOptionClick, 'sliders') - ] - - var optionsPanel = UI.MenubarHelper.createOptionsPanel(menuConfig) - - return UI.MenubarHelper.createMenuContainer('Help', optionsPanel) -} - -// Overview - -NGL.OverviewWidget = function (stage, preferences) { - var container = new UI.OverlayPanel() - - var xOffset = 0 - var yOffset = 0 - - var prevX = 0 - var prevY = 0 - - function onMousemove (e) { - if (prevX === 0) { - prevX = e.clientX - prevY = e.clientY - } - xOffset -= prevX - e.clientX - yOffset -= prevY - e.clientY - prevX = e.clientX - prevY = e.clientY - container.dom.style.top = yOffset + 'px' - container.dom.style.left = xOffset + 'px' - } - - function setWidgetPosition (left, top) { - xOffset = left - yOffset = top - prevX = 0 - prevY = 0 - container.dom.style.top = yOffset + 'px' - container.dom.style.left = xOffset + 'px' - } - container.setWidgetPosition = setWidgetPosition - - var headingPanel = new UI.Panel() - .setBorderBottom('1px solid #555') - .setHeight('25px') - .setCursor('move') - .onMouseDown(function (e) { - if (e.which === 1) { - document.addEventListener('mousemove', onMousemove) - } - document.addEventListener('mouseup', function (e) { - document.removeEventListener('mousemove', onMousemove) - }) - }) - - var listingPanel = new UI.Panel() - .setMarginTop('10px') - .setMinHeight('100px') - .setMaxHeight('500px') - .setMaxWidth('600px') - .setOverflow('auto') - - headingPanel.add( - new UI.Text('NGL Viewer').setFontStyle('italic'), - new UI.Html(' — Overview') - ) - headingPanel.add( - new UI.Icon('times') - .setCursor('pointer') - .setMarginLeft('20px') - .setFloat('right') - .onClick(function () { - container.setDisplay('none') - }) - ) - - container.add(headingPanel) - container.add(listingPanel) - - // - - function addIcon (name, text) { - var panel = new UI.Panel() - - var icon = new UI.Icon(name) - .setWidth('20px') - .setFloat('left') - - var label = new UI.Text(text) - .setDisplay('inline') - .setMarginLeft('5px') - - panel - .setMarginLeft('20px') - .add(icon, label) - listingPanel.add(panel) - } - - listingPanel - .add(new UI.Panel().add(new UI.Html("To load a new structure use the File menu in the top left via drag'n'drop."))) - .add(new UI.Break()) - - listingPanel - .add(new UI.Panel().add(new UI.Text('A number of clickable icons provide common actions. Most icons can be clicked on, just try it or hover the mouse pointer over it to see a tooltip.'))) - .add(new UI.Break()) - - addIcon('eye', 'Controls the visibility of a component.') - addIcon('trash-o', 'Deletes a component. Note that a second click is required to confirm the action.') - addIcon('bullseye', 'Centers a component.') - addIcon('bars', 'Opens a menu with further options.') - addIcon('square', 'Opens a menu with coloring options.') - addIcon('filter', 'Indicates atom-selection input fields.') - - listingPanel - .add(new UI.Text('Mouse controls')) - .add(new UI.Html( - '
    ' + - '
  • Left button hold and move to rotate camera around center.
  • ' + - '
  • Left button click to pick atom.
  • ' + - '
  • Middle button hold and move to zoom camera in and out.
  • ' + - '
  • Middle button click to center camera on atom.
  • ' + - '
  • Right button hold and move to translate camera in the screen plane.
  • ' + - '
' - )) - - listingPanel - .add(new UI.Panel().add(new UI.Html( - 'For more information please visit the ' + - "
documentation pages." - ))) - - var overview = preferences.getKey('overview') - var showOverviewCheckbox = new UI.Checkbox(overview) - .onClick(function () { - preferences.setKey( - 'overview', - showOverviewCheckbox.getValue() - ) - }) - - listingPanel - .add(new UI.HorizontalRule() - .setBorderTop('1px solid #555') - .setMarginTop('15px') - ) - .add(new UI.Panel().add( - showOverviewCheckbox, - new UI.Text( - 'Show on startup. Always available from Menu > Help > Overview.' - ).setMarginLeft('5px') - )) - - return container -} - -// Preferences - -NGL.PreferencesWidget = function (stage, preferences) { - var container = new UI.OverlayPanel() - - var xOffset = 0 - var yOffset = 0 - - var prevX = 0 - var prevY = 0 - - function onMousemove (e) { - if (prevX === 0) { - prevX = e.clientX - prevY = e.clientY - } - xOffset -= prevX - e.clientX - yOffset -= prevY - e.clientY - prevX = e.clientX - prevY = e.clientY - container.dom.style.top = yOffset + 'px' - container.dom.style.left = xOffset + 'px' - } - - function setWidgetPosition (left, top) { - xOffset = left - yOffset = top - prevX = 0 - prevY = 0 - container.dom.style.top = yOffset + 'px' - container.dom.style.left = xOffset + 'px' - } - container.setWidgetPosition = setWidgetPosition - - var headingPanel = new UI.Panel() - .setBorderBottom('1px solid #555') - .setHeight('25px') - .setCursor('move') - .onMouseDown(function (e) { - if (e.which === 1) { - document.addEventListener('mousemove', onMousemove) - } - document.addEventListener('mouseup', function (e) { - document.removeEventListener('mousemove', onMousemove) - }) - }) - - var listingPanel = new UI.Panel() - .setMarginTop('10px') - .setMinHeight('100px') - .setMaxHeight('500px') - .setOverflow('auto') - - headingPanel.add(new UI.Text('Preferences')) - headingPanel.add( - new UI.Icon('times') - .setCursor('pointer') - .setMarginLeft('20px') - .setFloat('right') - .onClick(function () { - container.setDisplay('none') - }) - ) - - container.add(headingPanel) - container.add(listingPanel) - - // - - Object.keys(NGL.UIStageParameters).forEach(function (name) { - var p = NGL.UIStageParameters[ name ] - if (p.label === undefined) p.label = name - var input = NGL.createParameterInput(p, stage.parameters[ name ]) - - if (!input) return - - preferences.signals.keyChanged.add(function (key, value) { - if (key === name) input.setValue(value) - }) - - function setParam () { - var sp = {} - sp[ name ] = input.getValue() - preferences.setKey(name, sp[ name ]) - } - - var ua = navigator.userAgent - if (p.type === 'range' && !/Trident/.test(ua) && !/MSIE/.test(ua)) { - input.onInput(setParam) - } else { - input.onChange(setParam) - } - - listingPanel - .add(new UI.Text(name).setWidth('120px')) - .add(input) - .add(new UI.Break()) - }) - - return container -} - -// Export image - -NGL.ExportImageWidget = function (stage) { - var container = new UI.OverlayPanel() - - var headingPanel = new UI.Panel() - .setBorderBottom('1px solid #555') - .setHeight('25px') - - var listingPanel = new UI.Panel() - .setMarginTop('10px') - .setMinHeight('100px') - .setMaxHeight('500px') - .setOverflow('auto') - - headingPanel.add(new UI.Text('Image export')) - headingPanel.add( - new UI.Icon('times') - .setCursor('pointer') - .setMarginLeft('20px') - .setFloat('right') - .onClick(function () { - container.setDisplay('none') - }) - ) - - container.add(headingPanel) - container.add(listingPanel) - - var factorSelect = new UI.Select() - .setOptions({ - '1': '1x', - '2': '2x', - '3': '3x', - '4': '4x', - '5': '5x', - '6': '6x', - '7': '7x', - '8': '8x', - '9': '9x', - '10': '10x' - }) - .setValue('4') - - var antialiasCheckbox = new UI.Checkbox() - .setValue(true) - - var trimCheckbox = new UI.Checkbox() - .setValue(false) - - var transparentCheckbox = new UI.Checkbox() - .setValue(false) - - var progress = new UI.Progress() - .setDisplay('none') - - var exportButton = new UI.Button('export') - .onClick(function () { - exportButton.setDisplay('none') - progress.setDisplay('inline-block') - function onProgress (i, n, finished) { - if (i === 1) { - progress.setMax(n) - } - if (i >= n) { - progress.setIndeterminate() - } else { - progress.setValue(i) - } - if (finished) { - progress.setDisplay('none') - exportButton.setDisplay('inline-block') - } - } - - setTimeout(function () { - stage.makeImage({ - factor: parseInt(factorSelect.getValue()), - antialias: antialiasCheckbox.getValue(), - trim: trimCheckbox.getValue(), - transparent: transparentCheckbox.getValue(), - onProgress: onProgress - }).then(function (blob) { - NGL.download(blob, 'screenshot.png') - }) - }, 50) - }) - - function addEntry (label, entry) { - listingPanel - .add(new UI.Text(label).setWidth('80px')) - .add(entry || new UI.Panel()) - .add(new UI.Break()) - } - - addEntry('scale', factorSelect) - addEntry('antialias', antialiasCheckbox) - addEntry('trim', trimCheckbox) - addEntry('transparent', transparentCheckbox) - - listingPanel.add( - new UI.Break(), - exportButton, progress - ) - - return container -} - -// Sidebar - -NGL.SidebarWidget = function (stage) { - var signals = stage.signals - var container = new UI.Panel() - - var widgetContainer = new UI.Panel() - .setClass('Content') - - var compList = [] - var widgetList = [] - - signals.componentAdded.add(function (component) { - var widget - - switch (component.type) { - case 'structure': - widget = new NGL.StructureComponentWidget(component, stage) - break - - case 'surface': - widget = new NGL.SurfaceComponentWidget(component, stage) - break - - case 'volume': - widget = new NGL.VolumeComponentWidget(component, stage) - break - - case 'shape': - widget = new NGL.ShapeComponentWidget(component, stage) - break - - default: - console.warn('NGL.SidebarWidget: component type unknown', component) - return - } - - widgetContainer.add(widget) - - compList.push(component) - widgetList.push(widget) - }) - - signals.componentRemoved.add(function (component) { - var idx = compList.indexOf(component) - - if (idx !== -1) { - widgetList[ idx ].dispose() - - compList.splice(idx, 1) - widgetList.splice(idx, 1) - } - }) - - // actions - - var expandAll = new UI.Icon('plus-square') - .setTitle('expand all') - .setCursor('pointer') - .onClick(function () { - widgetList.forEach(function (widget) { - widget.expand() - }) - }) - - var collapseAll = new UI.Icon('minus-square') - .setTitle('collapse all') - .setCursor('pointer') - .setMarginLeft('10px') - .onClick(function () { - widgetList.forEach(function (widget) { - widget.collapse() - }) - }) - - var centerAll = new UI.Icon('bullseye') - .setTitle('center all') - .setCursor('pointer') - .setMarginLeft('10px') - .onClick(function () { - stage.autoView(1000) - }) - - var disposeAll = new UI.DisposeIcon() - .setMarginLeft('10px') - .setDisposeFunction(function () { - stage.removeAllComponents() - }) - - var settingsMenu = new UI.PopupMenu('cogs', 'Settings', 'window') - .setIconTitle('settings') - .setMarginLeft('10px') - settingsMenu.entryLabelWidth = '120px' - - // Busy indicator - - var busy = new UI.Panel() - .setDisplay('inline') - .add( - new UI.Icon('spinner') - .addClass('spin') - .setMarginLeft('45px') - ) - - stage.tasks.signals.countChanged.add(function (delta, count) { - if (count > 0) { - actions.add(busy) - } else { - try { - actions.remove(busy) - } catch (e) { - // already removed - } - } - }) - - var paramNames = [ - 'clipNear', 'clipFar', 'clipDist', 'fogNear', 'fogFar', - 'lightColor', 'lightIntensity', 'ambientColor', 'ambientIntensity' - ] - - paramNames.forEach(function (name) { - var p = NGL.UIStageParameters[ name ] - if (p.label === undefined) p.label = name - var input = NGL.createParameterInput(p, stage.parameters[ name ]) - - if (!input) return - - stage.signals.parametersChanged.add(function (params) { - input.setValue(params[ name ]) - }) - - function setParam () { - var sp = {} - sp[ name ] = input.getValue() - stage.setParameters(sp) - } - - var ua = navigator.userAgent - if (p.type === 'range' && !/Trident/.test(ua) && !/MSIE/.test(ua)) { - input.onInput(setParam) - } else { - input.onChange(setParam) - } - - settingsMenu.addEntry(name, input) - }) - - // - - var actions = new UI.Panel() - .setClass('Panel Sticky') - .add( - expandAll, - collapseAll, - centerAll, - disposeAll, - settingsMenu - ) - - container.add( - actions, - widgetContainer - ) - - return container -} - -// Component - -NGL.StructureComponentWidget = function (component, stage) { - var signals = component.signals - var container = new UI.CollapsibleIconPanel('minus-square', 'plus-square') - - var reprContainer = new UI.Panel() - var trajContainer = new UI.Panel() - - signals.representationAdded.add(function (repr) { - reprContainer.add( - new NGL.RepresentationElementWidget(repr, stage) - ) - }) - - signals.trajectoryAdded.add(function (traj) { - trajContainer.add(new NGL.TrajectoryElementWidget(traj, stage)) - }) - - signals.defaultAssemblyChanged.add(function () { - assembly.setValue(component.parameters.defaultAssembly) - }) - - // Selection - - container.add( - new UI.SelectionPanel(component.selection) - .setMarginLeft('20px') - .setInputWidth('214px') - ) - - // Export PDB - - var pdb = new UI.Button('export').onClick(function () { - var pdbWriter = new NGL.PdbWriter(component.structure) - pdbWriter.download('structure') - componentPanel.setMenuDisplay('none') - }) - - // Add representation - - var repr = new UI.Select() - .setColor('#444') - .setOptions((function () { - var reprOptions = { '': '[ add ]' } - NGL.RepresentationRegistry.names.forEach(function (key) { - reprOptions[ key ] = key - }) - return reprOptions - })()) - .onChange(function () { - component.addRepresentation(repr.getValue()) - repr.setValue('') - componentPanel.setMenuDisplay('none') - }) - - // Assembly - - var assembly = new UI.Select() - .setColor('#444') - .setOptions((function () { - var biomolDict = component.structure.biomolDict - var assemblyOptions = { - '': (component.structure.unitcell ? 'AU' : 'FULL') - } - Object.keys(biomolDict).forEach(function (k) { - assemblyOptions[ k ] = k - }) - return assemblyOptions - })()) - .setValue(component.parameters.defaultAssembly) - .onChange(function () { - component.setDefaultAssembly(assembly.getValue()) - componentPanel.setMenuDisplay('none') - }) - - // Open trajectory - - var trajExt = [] - NGL.ParserRegistry.getTrajectoryExtensions().forEach(function (ext) { - trajExt.push('.' + ext, '.' + ext + '.gz') - }) - - function framesInputOnChange (e) { - var fn = function (file, callback) { - NGL.autoLoad(file).then(function (frames) { - component.addTrajectory(frames) - callback() - }) - } - var queue = new NGL.Queue(fn, e.target.files) - e.target.value = '' - } - - var framesInput = document.createElement('input') - framesInput.type = 'file' - framesInput.multiple = true - framesInput.style.display = 'none' - framesInput.accept = trajExt.join(',') - framesInput.addEventListener('change', framesInputOnChange, false) - - var traj = new UI.Button('open').onClick(function () { - framesInput.click() - componentPanel.setMenuDisplay('none') - }) - - // Import remote trajectory - - var remoteTraj = new UI.Button('import').onClick(function () { - componentPanel.setMenuDisplay('none') - - // TODO list of extensions should be provided by trajectory datasource - var remoteTrajExt = [ - 'xtc', 'trr', 'netcdf', 'dcd', 'ncdf', 'nc', 'gro', 'pdb', - 'lammpstrj', 'xyz', 'mdcrd', 'gz', 'binpos', 'h5', 'dtr', - 'arc', 'tng', 'trj', 'trz' - ] - var dirWidget - - function onListingClick (info) { - var ext = info.path.split('.').pop().toLowerCase() - if (remoteTrajExt.indexOf(ext) !== -1) { - component.addTrajectory(info.path + '?struc=' + component.structure.path) - dirWidget.dispose() - } else { - NGL.log('unknown trajectory type: ' + ext) - } - } - - dirWidget = new NGL.DirectoryListingWidget( - NGL.ListingDatasource, stage, 'Import trajectory', - remoteTrajExt, onListingClick - ) - - dirWidget - .setOpacity('0.9') - .setLeft('50px') - .setTop('80px') - .attach() - }) - - // Superpose - - function setSuperposeOptions () { - var superposeOptions = { '': '[ structure ]' } - stage.eachComponent(function (o, i) { - if (o !== component) { - superposeOptions[ i ] = o.name - } - }, NGL.StructureComponent) - superpose.setOptions(superposeOptions) - } - - stage.signals.componentAdded.add(setSuperposeOptions) - stage.signals.componentRemoved.add(setSuperposeOptions) - - var superpose = new UI.Select() - .setColor('#444') - .onChange(function () { - component.superpose( - stage.compList[ superpose.getValue() ], - true - ) - component.autoView(1000) - superpose.setValue('') - componentPanel.setMenuDisplay('none') - }) - - setSuperposeOptions() - - // Principal axes - - var alignAxes = new UI.Button('align').onClick(function () { - var pa = component.structure.getPrincipalAxes() - var q = pa.getRotationQuaternion() - q.multiply(component.quaternion.clone().inverse()) - stage.animationControls.rotate(q) - stage.animationControls.move(component.getCenter()) - }) - - // Measurements removal - - var removeMeasurements = new UI.Button('remove').onClick(function () { - component.removeAllMeasurements() - }) - - // Annotations visibility - - var showAnnotations = new UI.Button('show').onClick(function () { - component.annotationList.forEach(function (annotation) { - annotation.setVisibility(true) - }) - }) - - var hideAnnotations = new UI.Button('hide').onClick(function () { - component.annotationList.forEach(function (annotation) { - annotation.setVisibility(false) - }) - }) - - var annotationButtons = new UI.Panel() - .setDisplay('inline-block') - .add(showAnnotations, hideAnnotations) - - // Open validation - - function validationInputOnChange (e) { - var fn = function (file, callback) { - NGL.autoLoad(file, { ext: 'validation' }).then(function (validation) { - component.structure.validation = validation - callback() - }) - } - var queue = new NGL.Queue(fn, e.target.files) - } - - var validationInput = document.createElement('input') - validationInput.type = 'file' - validationInput.style.display = 'none' - validationInput.accept = '.xml' - validationInput.addEventListener('change', validationInputOnChange, false) - - var vali = new UI.Button('open').onClick(function () { - validationInput.click() - componentPanel.setMenuDisplay('none') - }) - - // Position - - var position = new UI.Vector3() - .onChange(function () { - component.setPosition(position.getValue()) - }) - - // Rotation - - var q = new NGL.Quaternion() - var e = new NGL.Euler() - var rotation = new UI.Vector3() - .setRange(-6.28, 6.28) - .onChange(function () { - e.setFromVector3(rotation.getValue()) - q.setFromEuler(e) - component.setRotation(q) - }) - - // Scale - - var scale = new UI.Number(1) - .setRange(0.01, 100) - .onChange(function () { - component.setScale(scale.getValue()) - }) - - // Matrix - - signals.matrixChanged.add(function () { - position.setValue(component.position) - rotation.setValue(e.setFromQuaternion(component.quaternion)) - scale.setValue(component.scale.x) - }) - - // Component panel - - var componentPanel = new UI.ComponentPanel(component) - .setDisplay('inline-block') - .setMargin('0px') - .addMenuEntry('PDB file', pdb) - .addMenuEntry('Representation', repr) - .addMenuEntry('Assembly', assembly) - .addMenuEntry('Superpose', superpose) - .addMenuEntry( - 'File', new UI.Text(component.structure.path) - .setMaxWidth('100px') - .setOverflow('auto') - // .setWordWrap( "break-word" ) - ) - .addMenuEntry('Trajectory', traj) - .addMenuEntry('Principal axes', alignAxes) - .addMenuEntry('Measurements', removeMeasurements) - .addMenuEntry('Annotations', annotationButtons) - .addMenuEntry('Validation', vali) - .addMenuEntry('Position', position) - .addMenuEntry('Rotation', rotation) - .addMenuEntry('Scale', scale) - - if (NGL.ListingDatasource && NGL.TrajectoryDatasource) { - componentPanel.addMenuEntry('Remote trajectory', remoteTraj) - } - - // Fill container - - container - .addStatic(componentPanel) - .add(trajContainer) - .add(reprContainer) - - return container -} - -NGL.SurfaceComponentWidget = function (component, stage) { - var signals = component.signals - var container = new UI.CollapsibleIconPanel('minus-square', 'plus-square') - - var reprContainer = new UI.Panel() - - signals.representationAdded.add(function (repr) { - reprContainer.add( - new NGL.RepresentationElementWidget(repr, stage) - ) - }) - - // Add representation - - var repr = new UI.Select() - .setColor('#444') - .setOptions((function () { - var reprOptions = { - '': '[ add ]', - 'surface': 'surface', - 'dot': 'dot' - } - return reprOptions - })()) - .onChange(function () { - component.addRepresentation(repr.getValue()) - repr.setValue('') - componentPanel.setMenuDisplay('none') - }) - - // Position - - var position = new UI.Vector3() - .onChange(function () { - component.setPosition(position.getValue()) - }) - - // Rotation - - var q = new NGL.Quaternion() - var e = new NGL.Euler() - var rotation = new UI.Vector3() - .setRange(-6.28, 6.28) - .onChange(function () { - e.setFromVector3(rotation.getValue()) - q.setFromEuler(e) - component.setRotation(q) - }) - - // Scale - - var scale = new UI.Number(1) - .setRange(0.01, 100) - .onChange(function () { - component.setScale(scale.getValue()) - }) - - // Matrix - - signals.matrixChanged.add(function () { - position.setValue(component.position) - rotation.setValue(e.setFromQuaternion(component.quaternion)) - scale.setValue(component.scale.x) - }) - - // Component panel - - var componentPanel = new UI.ComponentPanel(component) - .setDisplay('inline-block') - .setMargin('0px') - .addMenuEntry('Representation', repr) - .addMenuEntry( - 'File', new UI.Text(component.surface.path) - .setMaxWidth('100px') - .setWordWrap('break-word')) - .addMenuEntry('Position', position) - .addMenuEntry('Rotation', rotation) - .addMenuEntry('Scale', scale) - - // Fill container - - container - .addStatic(componentPanel) - .add(reprContainer) - - return container -} - -NGL.VolumeComponentWidget = function (component, stage) { - var signals = component.signals - var container = new UI.CollapsibleIconPanel('minus-square', 'plus-square') - - var reprContainer = new UI.Panel() - - signals.representationAdded.add(function (repr) { - reprContainer.add( - new NGL.RepresentationElementWidget(repr, stage) - ) - }) - - // Add representation - - var repr = new UI.Select() - .setColor('#444') - .setOptions((function () { - var reprOptions = { - '': '[ add ]', - 'surface': 'surface', - 'dot': 'dot', - 'slice': 'slice' - } - return reprOptions - })()) - .onChange(function () { - component.addRepresentation(repr.getValue()) - repr.setValue('') - componentPanel.setMenuDisplay('none') - }) - - // Position - - var position = new UI.Vector3() - .onChange(function () { - component.setPosition(position.getValue()) - }) - - // Rotation - - var q = new NGL.Quaternion() - var e = new NGL.Euler() - var rotation = new UI.Vector3() - .setRange(-6.28, 6.28) - .onChange(function () { - e.setFromVector3(rotation.getValue()) - q.setFromEuler(e) - component.setRotation(q) - }) - - // Scale - - var scale = new UI.Number(1) - .setRange(0.01, 100) - .onChange(function () { - component.setScale(scale.getValue()) - }) - - // Matrix - - signals.matrixChanged.add(function () { - position.setValue(component.position) - rotation.setValue(e.setFromQuaternion(component.quaternion)) - scale.setValue(component.scale.x) - }) - - // Component panel - - var componentPanel = new UI.ComponentPanel(component) - .setDisplay('inline-block') - .setMargin('0px') - .addMenuEntry('Representation', repr) - .addMenuEntry( - 'File', new UI.Text(component.volume.path) - .setMaxWidth('100px') - .setWordWrap('break-word')) - .addMenuEntry('Position', position) - .addMenuEntry('Rotation', rotation) - .addMenuEntry('Scale', scale) - - // Fill container - - container - .addStatic(componentPanel) - .add(reprContainer) - - return container -} - -NGL.ShapeComponentWidget = function (component, stage) { - var signals = component.signals - var container = new UI.CollapsibleIconPanel('minus-square', 'plus-square') - - var reprContainer = new UI.Panel() - - signals.representationAdded.add(function (repr) { - reprContainer.add( - new NGL.RepresentationElementWidget(repr, stage) - ) - }) - - // Add representation - - var repr = new UI.Select() - .setColor('#444') - .setOptions((function () { - var reprOptions = { - '': '[ add ]', - 'buffer': 'buffer' - } - return reprOptions - })()) - .onChange(function () { - component.addRepresentation(repr.getValue()) - repr.setValue('') - componentPanel.setMenuDisplay('none') - }) - - // Position - - var position = new UI.Vector3() - .onChange(function () { - component.setPosition(position.getValue()) - }) - - // Rotation - - var q = new NGL.Quaternion() - var e = new NGL.Euler() - var rotation = new UI.Vector3() - .setRange(-6.28, 6.28) - .onChange(function () { - e.setFromVector3(rotation.getValue()) - q.setFromEuler(e) - component.setRotation(q) - }) - - // Scale - - var scale = new UI.Number(1) - .setRange(0.01, 100) - .onChange(function () { - component.setScale(scale.getValue()) - }) - - // Matrix - - signals.matrixChanged.add(function () { - position.setValue(component.position) - rotation.setValue(e.setFromQuaternion(component.quaternion)) - scale.setValue(component.scale.x) - }) - - // Component panel - - var componentPanel = new UI.ComponentPanel(component) - .setDisplay('inline-block') - .setMargin('0px') - .addMenuEntry('Representation', repr) - .addMenuEntry( - 'File', new UI.Text(component.shape.path) - .setMaxWidth('100px') - .setWordWrap('break-word')) - .addMenuEntry('Position', position) - .addMenuEntry('Rotation', rotation) - .addMenuEntry('Scale', scale) - - // Fill container - - container - .addStatic(componentPanel) - .add(reprContainer) - - return container -} - -// Representation - -NGL.RepresentationElementWidget = function (element, stage) { - var signals = element.signals - - var container = new UI.CollapsibleIconPanel('minus-square', 'plus-square') - .setMarginLeft('20px') - - signals.visibilityChanged.add(function (value) { - toggle.setValue(value) - }) - - signals.nameChanged.add(function (value) { - name.setValue(value) - }) - - signals.disposed.add(function () { - menu.dispose() - container.dispose() - }) - - // Name - - var name = new UI.EllipsisText(element.name) - .setWidth('103px') - - // Actions - - var toggle = new UI.ToggleIcon(element.visible, 'eye', 'eye-slash') - .setTitle('hide/show') - .setCursor('pointer') - .setMarginLeft('25px') - .onClick(function () { - element.setVisibility(!element.visible) - }) - - var disposeIcon = new UI.DisposeIcon() - .setMarginLeft('10px') - .setDisposeFunction(function () { - element.dispose() - }) - - container - .addStatic(name) - .addStatic(toggle) - .addStatic(disposeIcon) - - // Selection - - if ((element.parent.type === 'structure' || - element.parent.type === 'trajectory') && - element.repr.selection && element.repr.selection.type === 'selection' - ) { - container.add( - new UI.SelectionPanel(element.repr.selection) - .setMarginLeft('20px') - .setInputWidth('194px') - ) - } - - // Menu - - var menu = new UI.PopupMenu('bars', 'Representation') - .setMarginLeft('45px') - .setEntryLabelWidth('190px') - - menu.addEntry('type', new UI.Text(element.repr.type)) - - // Parameters - - var repr = element.repr - var rp = repr.getParameters() - - Object.keys(repr.parameters).forEach(function (name) { - if (!repr.parameters[ name ]) return - var p = Object.assign({}, repr.parameters[ name ]) - p.value = rp[ name ] - if (p.label === undefined) p.label = name - var input = NGL.createParameterInput(p) - - if (!input) return - - signals.parametersChanged.add(function (params) { - if (typeof input.setValue === 'function') { - input.setValue(params[ name ]) - } - }) - - function setParam () { - var po = {} - po[ name ] = input.getValue() - element.setParameters(po) - stage.viewer.requestRender() - } - - var ua = navigator.userAgent - if (p.type === 'range' && !/Trident/.test(ua) && !/MSIE/.test(ua)) { - input.onInput(setParam) - } else { - input.onChange(setParam) - } - - menu.addEntry(name, input) - }) - - container - .addStatic(menu) - - return container -} - -// Trajectory - -NGL.TrajectoryElementWidget = function (element, stage) { - var signals = element.signals - var traj = element.trajectory - - var container = new UI.CollapsibleIconPanel('minus-square', 'plus-square') - .setMarginLeft('20px') - - signals.disposed.add(function () { - menu.dispose() - container.dispose() - }) - - var frameCount = new UI.Panel() - .setDisplay('inline') - .add(new UI.Icon('spinner') - .addClass('spin') - .setMarginRight('99px') - ) - - var frameTime = new UI.Panel() - .setMarginLeft('5px') - .setDisplay('inline') - - function setFrame (value) { - frame.setValue(value) - if (traj.deltaTime && value >= 0) { - var t = traj.getFrameTime(value) / 1000 - time.setValue(t.toFixed(9).replace(/\.?0+$/g, '') + 'ns') - } else { - time.setValue('') - } - frameRange.setValue(value) - frameCount.clear().add(frame.setWidth('40px')) - frameTime.clear().add(time.setWidth('90px')) - } - - function init (value) { - frame.setRange(-1, value - 1) - frameRange.setRange(-1, value - 1) - - setFrame(traj.currentFrame) - - if (element.parameters.defaultStep !== undefined) { - step.setValue(element.parameters.defaultStep) - } else { - // 1000 = n / step - step.setValue(Math.ceil((value + 1) / 100)) - } - - player.setParameters({step: step.getValue()}) - player.setParameters({end: value - 1}) - } - - signals.countChanged.add(init) - signals.frameChanged.add(setFrame) - - // Name - - var name = new UI.EllipsisText(element.parameters.name) - .setWidth('103px') - - signals.nameChanged.add(function (value) { - name.setValue(value) - }) - - container.addStatic(name) - container.addStatic(frameTime) - - // frames - - var frame = new UI.Integer(-1) - .setWidth('40px') - .setTextAlign('right') - .setMarginLeft('5px') - .setRange(-1, -1) - .onChange(function (e) { - traj.setFrame(frame.getValue()) - menu.setMenuDisplay('none') - }) - - var time = new UI.Text() - .setTextAlign('right') - .setWidth('90px') - - var step = new UI.Integer(1) - .setWidth('50px') - .setRange(1, 10000) - .onChange(function () { - player.setParameters({step: step.getValue()}) - }) - - var frameRow = new UI.Panel() - - var frameRange = new UI.Range(-1, -1, -1, 1) - .setWidth('147px') - .setMargin('0px') - .setPadding('0px') - .setBorder('0px') - .onInput(function (e) { - var value = frameRange.getValue() - - if (value === traj.currentFrame) { - return - } - - if (traj.player && traj.player.isRunning) { - traj.setPlayer() - traj.setFrame(value) - } else if (!traj.inProgress) { - traj.setFrame(value) - } - }) - - var interpolateType = new UI.Select() - .setColor('#444') - .setOptions({ - '': 'none', - 'linear': 'linear', - 'spline': 'spline' - }) - .setValue(element.parameters.defaultInterpolateType) - .onChange(function () { - player.setParameters({interpolateType: interpolateType.getValue()}) - }) - - var interpolateStep = new UI.Integer(element.parameters.defaultInterpolateStep) - .setWidth('30px') - .setRange(1, 50) - .onChange(function () { - player.setParameters({interpolateStep: interpolateStep.getValue()}) - }) - - var playDirection = new UI.Select() - .setColor('#444') - .setOptions({ - 'forward': 'forward', - 'backward': 'backward', - 'bounce': 'bounce' - }) - .setValue(element.parameters.defaultDirection) - .onChange(function () { - player.setParameters({direction: playDirection.getValue()}) - }) - - var playMode = new UI.Select() - .setColor('#444') - .setOptions({ - 'loop': 'loop', - 'once': 'once' - }) - .setValue(element.parameters.defaultMode) - .onChange(function () { - player.setParameters({mode: playMode.getValue()}) - }) - - // player - - var timeout = new UI.Integer(element.parameters.defaultTimeout) - .setWidth('30px') - .setRange(10, 1000) - .onChange(function () { - player.setParameters({timeout: timeout.getValue()}) - }) - - var player = new NGL.TrajectoryPlayer(traj, { - step: step.getValue(), - timeout: timeout.getValue(), - start: 0, - end: traj.frameCount - 1, - interpolateType: interpolateType.getValue(), - interpolateStep: interpolateStep.getValue(), - direction: playDirection.getValue(), - mode: playMode.getValue() - }) - traj.setPlayer(player) - - var playerButton = new UI.ToggleIcon(true, 'play', 'pause') - .setMarginRight('10px') - .setMarginLeft('20px') - .setCursor('pointer') - .setWidth('12px') - .setTitle('play') - .onClick(function () { - player.toggle() - }) - - player.signals.startedRunning.add(function () { - playerButton - .setTitle('pause') - .setValue(false) - }) - - player.signals.haltedRunning.add(function () { - playerButton - .setTitle('play') - .setValue(true) - }) - - frameRow.add(playerButton, frameRange, frameCount) - - // Selection - - container.add( - new UI.SelectionPanel(traj.selection) - .setMarginLeft('20px') - .setInputWidth('194px') - ) - - // Options - - var setCenterPbc = new UI.Checkbox(traj.centerPbc) - .onChange(function () { - element.setParameters({ - 'centerPbc': setCenterPbc.getValue() - }) - }) - - var setRemovePeriodicity = new UI.Checkbox(traj.removePeriodicity) - .onChange(function () { - element.setParameters({ - 'removePeriodicity': setRemovePeriodicity.getValue() - }) - }) - - var setRemovePbc = new UI.Checkbox(traj.removePbc) - .onChange(function () { - element.setParameters({ - 'removePbc': setRemovePbc.getValue() - }) - }) - - var setSuperpose = new UI.Checkbox(traj.superpose) - .onChange(function () { - element.setParameters({ - 'superpose': setSuperpose.getValue() - }) - }) - - var setDeltaTime = new UI.Number(traj.deltaTime) - .setWidth('55px') - .setRange(0, 1000000) - .onChange(function () { - element.setParameters({ - 'deltaTime': setDeltaTime.getValue() - }) - }) - - var setTimeOffset = new UI.Number(traj.timeOffset) - .setWidth('55px') - .setRange(0, 1000000000) - .onChange(function () { - element.setParameters({ - 'timeOffset': setTimeOffset.getValue() - }) - }) - - signals.parametersChanged.add(function (params) { - setCenterPbc.setValue(traj.centerPbc) - setRemovePeriodicity.setValue(traj.removePeriodicity) - setRemovePbc.setValue(traj.removePbc) - setSuperpose.setValue(traj.superpose) - setDeltaTime.setValue(traj.deltaTime) - setTimeOffset.setValue(traj.timeOffset) - traj.setFrame(frame.getValue()) - }) - - // Dispose - - var dispose = new UI.DisposeIcon() - .setDisposeFunction(function () { - element.parent.removeTrajectory(element) - }) - - // - - if (traj.frameCount) { - init(traj.frameCount) - } - - // Menu - - var menu = new UI.PopupMenu('bars', 'Trajectory') - .setMarginLeft('10px') - .setEntryLabelWidth('130px') - .addEntry('Center', setCenterPbc) - .addEntry('Remove Periodicity', setRemovePeriodicity) - .addEntry('Remove PBC', setRemovePbc) - .addEntry('Superpose', setSuperpose) - .addEntry('Step size', step) - .addEntry('Interpolation type', interpolateType) - .addEntry('Interpolation steps', interpolateStep) - .addEntry('Play timeout', timeout) - .addEntry('Play direction', playDirection) - .addEntry('Play mode', playMode) - .addEntry('Delta time [ps]', setDeltaTime) - .addEntry('Time offset [ps]', setTimeOffset) - .addEntry('File', - new UI.Text(traj.trajPath) - .setMaxWidth('100px') - .setWordWrap('break-word')) - .addEntry('Dispose', dispose) - - container - .addStatic(menu) - - container - .add(frameRow) - - return container -} - -// Listing - -NGL.DirectoryListingWidget = function (datasource, stage, heading, filter, callback) { - // from http://stackoverflow.com/a/20463021/1435042 - function fileSizeSI (a, b, c, d, e) { - return (b = Math, c = b.log, d = 1e3, e = c(a) / c(d) | 0, a / b.pow(d, e)).toFixed(2) + - String.fromCharCode(160) + (e ? 'kMGTPEZY'[--e] + 'B' : 'Bytes') - } - - function getFolderDict (path) { - path = path || '' - var options = { '': '' } - var full = [] - path.split('/').forEach(function (chunk) { - full.push(chunk) - options[ full.join('/') ] = chunk - }) - return options - } - - var container = new UI.OverlayPanel() - - var headingPanel = new UI.Panel() - .setBorderBottom('1px solid #555') - .setHeight('30px') - - var listingPanel = new UI.Panel() - .setMarginTop('10px') - .setMinHeight('100px') - .setMaxHeight('500px') - .setPaddingRight('15px') - .setOverflow('auto') - - var folderSelect = new UI.Select() - .setColor('#444') - .setMarginLeft('20px') - .setWidth('') - .setMaxWidth('200px') - .setOptions(getFolderDict()) - .onChange(function () { - datasource.getListing(folderSelect.getValue()) - .then(onListingLoaded) - }) - - heading = heading || 'Directoy listing' - - headingPanel.add(new UI.Text(heading)) - headingPanel.add(folderSelect) - headingPanel.add( - new UI.Icon('times') - .setCursor('pointer') - .setMarginLeft('20px') - .setFloat('right') - .onClick(function () { - container.dispose() - }) - ) - - container.add(headingPanel) - container.add(listingPanel) - - function onListingLoaded (listing) { - var folder = listing.path - var data = listing.data - - NGL.lastUsedDirectory = folder - listingPanel.clear() - - folderSelect - .setOptions(getFolderDict(folder)) - .setValue(folder) - - data.forEach(function (info) { - var ext = info.path.split('.').pop().toLowerCase() - if (filter && !info.dir && filter.indexOf(ext) === -1) { - return - } - - var icon, name - if (info.dir) { - icon = 'folder-o' - name = info.name - } else { - icon = 'file-o' - name = info.name + String.fromCharCode(160) + - '(' + fileSizeSI(info.size) + ')' - } - - var pathRow = new UI.Panel() - .setDisplay('block') - .setWhiteSpace('nowrap') - .add(new UI.Icon(icon).setWidth('20px')) - .add(new UI.Text(name)) - .onClick(function () { - if (info.dir) { - datasource.getListing(info.path) - .then(onListingLoaded) - } else { - callback(info) - } - }) - - if (info.restricted) { - pathRow.add(new UI.Icon('lock').setMarginLeft('5px')) - } - - listingPanel.add(pathRow) - }) - } - - datasource.getListing(NGL.lastUsedDirectory) - .then(onListingLoaded) - - return container -} diff --git a/examples/examples/js/lib/colorpicker.min.js b/examples/examples/js/lib/colorpicker.min.js deleted file mode 100644 index fbbf7ab5f..000000000 --- a/examples/examples/js/lib/colorpicker.min.js +++ /dev/null @@ -1,14 +0,0 @@ -if( typeof importScripts !== 'function' ){ -(function(w,l,r){function s(a,c){var d=c.getBoundingClientRect();return{x:Math.max(Math.min(a.clientX-d.left,c.clientWidth),0),y:Math.max(Math.min(a.clientY-d.top,c.clientHeight),0)}}function f(a,c,d){a=l.createElementNS("http://www.w3.org/2000/svg",a);for(var b in c)a.setAttribute(b,c[b]);Array.isArray(d)||(d=[d]);c=0;for(b=d[0]&&d.length||0;c
', -this.slideElement=a.getElementsByClassName("slide")[0],this.pickerElement=a.getElementsByClassName("picker")[0],this.slideIndicator=a.getElementsByClassName("slide-indicator")[0],this.pickerIndicator=a.getElementsByClassName("picker-indicator")[0],g.positionIndicators(this.slideIndicator,this.pickerIndicator,{x:0,y:0},{x:0,y:0}),this.callback=function(a,b,d,e,f){g.positionIndicators(this.slideIndicator,this.pickerIndicator,f,e);c(a,b,d)});this.slide_listener=x(this,this.slideElement,this.pickerElement); -this.picker_listener=y(this,this.pickerElement);d||this.fixIndicators(this.slideIndicator,this.pickerIndicator);a=t.cloneNode(!0);d=u.cloneNode(!0);var b=a.getElementsByTagName("defs")[0].firstChild,e=a.getElementsByTagName("rect")[0];b.id="gradient-hsv-"+n;e.setAttribute("fill","url(#"+b.id+")");b=d.getElementsByTagName("defs")[0];b=[b.firstChild,b.lastChild];e=d.getElementsByTagName("rect");b[0].id="gradient-black-"+n;b[1].id="gradient-white-"+n;e[0].setAttribute("fill","url(#"+b[1].id+")");e[1].setAttribute("fill", -"url(#"+b[0].id+")");this.slideElement.appendChild(a);this.pickerElement.appendChild(d);n++;p(this.slideElement,this.slide_listener);p(this.pickerElement,this.picker_listener)}function p(a,c){function d(a){e&&c(a)}function b(a){d(a);e=!1;l.removeEventListener("mouseup",b,!1);l.removeEventListener("mousemove",d,!1)}var e=!1;a.addEventListener("mousedown",function(a){e=!0;a.preventDefault();l.addEventListener("mouseup",b,!0);l.addEventListener("mousemove",d,!1)},!1)}function q(a,c,d,b){a.h=c.h%360; -a.s=c.s;a.v=c.v;c=k(a);var e={y:a.h*a.slideElement.offsetHeight/360,x:0},f=a.pickerElement.offsetHeight,f={x:a.s*a.pickerElement.offsetWidth,y:f-a.v*f};a.pickerElement.style.backgroundColor=k({h:a.h,s:1,v:1}).hex;a.callback&&a.callback(b||c.hex,{h:a.h,s:a.s,v:a.v},d||{r:c.r,g:c.g,b:c.b},f,e);return a}var u,t,v={xmlns:"http://www.w3.org/2000/svg",version:"1.1",width:"100%",height:"100%"};t=f("svg",v,[f("defs",{},f("linearGradient",{id:"gradient-hsv",x1:"0%",y1:"100%",x2:"0%",y2:"0%"},[f("stop",{offset:"0%", -"stop-color":"#FF0000","stop-opacity":"1"}),f("stop",{offset:"13%","stop-color":"#FF00FF","stop-opacity":"1"}),f("stop",{offset:"25%","stop-color":"#8000FF","stop-opacity":"1"}),f("stop",{offset:"38%","stop-color":"#0040FF","stop-opacity":"1"}),f("stop",{offset:"50%","stop-color":"#00FFFF","stop-opacity":"1"}),f("stop",{offset:"63%","stop-color":"#00FF40","stop-opacity":"1"}),f("stop",{offset:"75%","stop-color":"#0BED00","stop-opacity":"1"}),f("stop",{offset:"88%","stop-color":"#FFFF00","stop-opacity":"1"}), -f("stop",{offset:"100%","stop-color":"#FF0000","stop-opacity":"1"})])),f("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:"url(#gradient-hsv)"})]);u=f("svg",v,[f("defs",{},[f("linearGradient",{id:"gradient-black",x1:"0%",y1:"100%",x2:"0%",y2:"0%"},[f("stop",{offset:"0%","stop-color":"#000000","stop-opacity":"1"}),f("stop",{offset:"100%","stop-color":"#CC9A81","stop-opacity":"0"})]),f("linearGradient",{id:"gradient-white",x1:"0%",y1:"100%",x2:"100%",y2:"100%"},[f("stop",{offset:"0%","stop-color":"#FFFFFF", -"stop-opacity":"1"}),f("stop",{offset:"100%","stop-color":"#CC9A81","stop-opacity":"0"})])]),f("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:"url(#gradient-white)"}),f("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:"url(#gradient-black)"})]);var n=0;g.hsv2rgb=function(a){a=k(a);delete a.hex;return a};g.hsv2hex=function(a){return k(a).hex};g.rgb2hsv=m;g.rgb2hex=function(a){return k(m(a)).hex};g.hex2hsv=function(a){return m(g.hex2rgb(a))};g.hex2rgb=function(a){return{r:parseInt(a.substr(1, -2),16),g:parseInt(a.substr(3,2),16),b:parseInt(a.substr(5,2),16)}};g.prototype.setHsv=function(a){return q(this,a)};g.prototype.setRgb=function(a){return q(this,m(a),a)};g.prototype.setHex=function(a){return q(this,g.hex2hsv(a),r,a)};g.positionIndicators=function(a,c,d,b){d&&(a.style.top=d.y-a.offsetHeight/2+"px");b&&(c.style.top=b.y-c.offsetHeight/2+"px",c.style.left=b.x-c.offsetWidth/2+"px")};g.prototype.fixIndicators=function(a,c){p(a,this.slide_listener);p(c,this.picker_listener)};w.ColorPicker= -g})(window,window.document); -} \ No newline at end of file diff --git a/examples/examples/js/lib/signals.min.js b/examples/examples/js/lib/signals.min.js deleted file mode 100644 index a4e36e8dc..000000000 --- a/examples/examples/js/lib/signals.min.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - - JS Signals - Released under the MIT license - Author: Miller Medeiros - Version: 1.0.0 - Build: 268 (2012/11/29 05:48 PM) -*/ -(function(i){function h(a,b,c,d,e){this._listener=b;this._isOnce=c;this.context=d;this._signal=a;this._priority=e||0}function g(a,b){if(typeof a!=="function")throw Error("listener is a required param of {fn}() and should be a Function.".replace("{fn}",b));}function e(){this._bindings=[];this._prevParams=null;var a=this;this.dispatch=function(){e.prototype.dispatch.apply(a,arguments)}}h.prototype={active:!0,params:null,execute:function(a){var b;this.active&&this._listener&&(a=this.params?this.params.concat(a): -a,b=this._listener.apply(this.context,a),this._isOnce&&this.detach());return b},detach:function(){return this.isBound()?this._signal.remove(this._listener,this.context):null},isBound:function(){return!!this._signal&&!!this._listener},isOnce:function(){return this._isOnce},getListener:function(){return this._listener},getSignal:function(){return this._signal},_destroy:function(){delete this._signal;delete this._listener;delete this.context},toString:function(){return"[SignalBinding isOnce:"+this._isOnce+ -", isBound:"+this.isBound()+", active:"+this.active+"]"}};e.prototype={VERSION:"1.0.0",memorize:!1,_shouldPropagate:!0,active:!0,_registerListener:function(a,b,c,d){var e=this._indexOfListener(a,c);if(e!==-1){if(a=this._bindings[e],a.isOnce()!==b)throw Error("You cannot add"+(b?"":"Once")+"() then add"+(!b?"":"Once")+"() the same listener without removing the relationship first.");}else a=new h(this,a,b,c,d),this._addBinding(a);this.memorize&&this._prevParams&&a.execute(this._prevParams);return a}, -_addBinding:function(a){var b=this._bindings.length;do--b;while(this._bindings[b]&&a._priority<=this._bindings[b]._priority);this._bindings.splice(b+1,0,a)},_indexOfListener:function(a,b){for(var c=this._bindings.length,d;c--;)if(d=this._bindings[c],d._listener===a&&d.context===b)return c;return-1},has:function(a,b){return this._indexOfListener(a,b)!==-1},add:function(a,b,c){g(a,"add");return this._registerListener(a,!1,b,c)},addOnce:function(a,b,c){g(a,"addOnce");return this._registerListener(a, -!0,b,c)},remove:function(a,b){g(a,"remove");var c=this._indexOfListener(a,b);c!==-1&&(this._bindings[c]._destroy(),this._bindings.splice(c,1));return a},removeAll:function(){for(var a=this._bindings.length;a--;)this._bindings[a]._destroy();this._bindings.length=0},getNumListeners:function(){return this._bindings.length},halt:function(){this._shouldPropagate=!1},dispatch:function(a){if(this.active){var b=Array.prototype.slice.call(arguments),c=this._bindings.length,d;if(this.memorize)this._prevParams= -b;if(c){d=this._bindings.slice();this._shouldPropagate=!0;do c--;while(d[c]&&this._shouldPropagate&&d[c].execute(b)!==!1)}}},forget:function(){this._prevParams=null},dispose:function(){this.removeAll();delete this._bindings;delete this._prevParams},toString:function(){return"[Signal active:"+this.active+" numListeners:"+this.getNumListeners()+"]"}};var f=e;f.Signal=e;typeof define==="function"&&define.amd?define(function(){return f}):typeof module!=="undefined"&&module.exports?module.exports=f:i.signals= -f})(this); \ No newline at end of file diff --git a/examples/examples/js/lib/tether.min.js b/examples/examples/js/lib/tether.min.js deleted file mode 100644 index 9d37fc03d..000000000 --- a/examples/examples/js/lib/tether.min.js +++ /dev/null @@ -1,3 +0,0 @@ -if( typeof importScripts !== 'function' ){ -!function(t,e){"function"==typeof define&&define.amd?define(e):"object"==typeof exports?module.exports=e(require,exports,module):t.Tether=e()}(this,function(t,e,o){"use strict";function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function n(t){var e=getComputedStyle(t),o=e.position;if("fixed"===o)return t;for(var i=t;i=i.parentNode;){var n=void 0;try{n=getComputedStyle(i)}catch(r){}if("undefined"==typeof n||null===n)return i;var s=n.overflow,a=n.overflowX,f=n.overflowY;if(/(auto|scroll)/.test(s+f+a)&&("absolute"!==o||["relative","absolute","fixed"].indexOf(n.position)>=0))return i}return document.body}function r(t){var e=void 0;t===document?(e=document,t=document.documentElement):e=t.ownerDocument;var o=e.documentElement,i={},n=t.getBoundingClientRect();for(var r in n)i[r]=n[r];var s=x(e);return i.top-=s.top,i.left-=s.left,"undefined"==typeof i.width&&(i.width=document.body.scrollWidth-i.left-i.right),"undefined"==typeof i.height&&(i.height=document.body.scrollHeight-i.top-i.bottom),i.top=i.top-o.clientTop,i.left=i.left-o.clientLeft,i.right=e.body.clientWidth-i.width-i.left,i.bottom=e.body.clientHeight-i.height-i.top,i}function s(t){return t.offsetParent||document.documentElement}function a(){var t=document.createElement("div");t.style.width="100%",t.style.height="200px";var e=document.createElement("div");f(e.style,{position:"absolute",top:0,left:0,pointerEvents:"none",visibility:"hidden",width:"200px",height:"150px",overflow:"hidden"}),e.appendChild(t),document.body.appendChild(e);var o=t.offsetWidth;e.style.overflow="scroll";var i=t.offsetWidth;o===i&&(i=e.clientWidth),document.body.removeChild(e);var n=o-i;return{width:n,height:n}}function f(){var t=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],e=[];return Array.prototype.push.apply(e,arguments),e.slice(1).forEach(function(e){if(e)for(var o in e)({}).hasOwnProperty.call(e,o)&&(t[o]=e[o])}),t}function h(t,e){if("undefined"!=typeof t.classList)e.split(" ").forEach(function(e){e.trim()&&t.classList.remove(e)});else{var o=new RegExp("(^| )"+e.split(" ").join("|")+"( |$)","gi"),i=u(t).replace(o," ");p(t,i)}}function l(t,e){if("undefined"!=typeof t.classList)e.split(" ").forEach(function(e){e.trim()&&t.classList.add(e)});else{h(t,e);var o=u(t)+(" "+e);p(t,o)}}function d(t,e){if("undefined"!=typeof t.classList)return t.classList.contains(e);var o=u(t);return new RegExp("(^| )"+e+"( |$)","gi").test(o)}function u(t){return t.className instanceof SVGAnimatedString?t.className.baseVal:t.className}function p(t,e){t.setAttribute("class",e)}function c(t,e,o){o.forEach(function(o){-1===e.indexOf(o)&&d(t,o)&&h(t,o)}),e.forEach(function(e){d(t,e)||l(t,e)})}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function g(t,e){var o=arguments.length<=2||void 0===arguments[2]?1:arguments[2];return t+o>=e&&e>=t-o}function m(){return"undefined"!=typeof performance&&"undefined"!=typeof performance.now?performance.now():+new Date}function v(){for(var t={top:0,left:0},e=arguments.length,o=Array(e),i=0;e>i;i++)o[i]=arguments[i];return o.forEach(function(e){var o=e.top,i=e.left;"string"==typeof o&&(o=parseFloat(o,10)),"string"==typeof i&&(i=parseFloat(i,10)),t.top+=o,t.left+=i}),t}function y(t,e){return"string"==typeof t.left&&-1!==t.left.indexOf("%")&&(t.left=parseFloat(t.left,10)/100*e.width),"string"==typeof t.top&&-1!==t.top.indexOf("%")&&(t.top=parseFloat(t.top,10)/100*e.height),t}function b(t,e){return"scrollParent"===e?e=t.scrollParent:"window"===e&&(e=[pageXOffset,pageYOffset,innerWidth+pageXOffset,innerHeight+pageYOffset]),e===document&&(e=e.documentElement),"undefined"!=typeof e.nodeType&&!function(){var t=r(e),o=t,i=getComputedStyle(e);e=[o.left,o.top,t.width+o.left,t.height+o.top],U.forEach(function(t,o){t=t[0].toUpperCase()+t.substr(1),"Top"===t||"Left"===t?e[o]+=parseFloat(i["border"+t+"Width"]):e[o]-=parseFloat(i["border"+t+"Width"])})}(),e}var w=function(){function t(t,e){for(var o=0;o1?a-1:0),h=1;a>h;h++)f[h-1]=arguments[h];i.apply(s,f),r?this.bindings[t].splice(e,1):++e}}}]),t}();C.Utils={getScrollParent:n,getBounds:r,getOffsetParent:s,extend:f,addClass:l,removeClass:h,hasClass:d,updateClasses:c,defer:T,flush:S,uniqueId:O,Evented:W,getScrollBarSize:a};var M=function(){function t(t,e){var o=[],i=!0,n=!1,r=void 0;try{for(var s,a=t[Symbol.iterator]();!(i=(s=a.next()).done)&&(o.push(s.value),!e||o.length!==e);i=!0);}catch(f){n=!0,r=f}finally{try{!i&&a["return"]&&a["return"]()}finally{if(n)throw r}}return o}return function(e,o){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,o);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),w=function(){function t(t,e){for(var o=0;o16?(e=Math.min(e-16,250),void(o=setTimeout(n,250))):void("undefined"!=typeof t&&m()-t<10||("undefined"!=typeof o&&(clearTimeout(o),o=null),t=m(),_(),e=m()-t))};["resize","scroll","touchmove"].forEach(function(t){window.addEventListener(t,i)})}();var z={center:"center",left:"right",right:"left"},F={middle:"middle",top:"bottom",bottom:"top"},L={top:0,left:0,middle:"50%",center:"50%",bottom:"100%",right:"100%"},Y=function(t,e){var o=t.left,i=t.top;return"auto"===o&&(o=z[e.left]),"auto"===i&&(i=F[e.top]),{left:o,top:i}},H=function(t){var e=t.left,o=t.top;return"undefined"!=typeof L[t.left]&&(e=L[t.left]),"undefined"!=typeof L[t.top]&&(o=L[t.top]),{left:e,top:o}},X=function(t){var e=t.split(" "),o=M(e,2),i=o[0],n=o[1];return{top:i,left:n}},j=X,N=function(){function t(e){var o=this;i(this,t),this.position=this.position.bind(this),B.push(this),this.history=[],this.setOptions(e,!1),C.modules.forEach(function(t){"undefined"!=typeof t.initialize&&t.initialize.call(o)}),this.position()}return w(t,[{key:"getClass",value:function(){var t=arguments.length<=0||void 0===arguments[0]?"":arguments[0],e=this.options.classes;return"undefined"!=typeof e&&e[t]?this.options.classes[t]:this.options.classPrefix?this.options.classPrefix+"-"+t:t}},{key:"setOptions",value:function(t){var e=this,o=arguments.length<=1||void 0===arguments[1]?!0:arguments[1],i={offset:"0 0",targetOffset:"0 0",targetAttachment:"auto auto",classPrefix:"tether"};this.options=f(i,t);var r=this.options,s=r.element,a=r.target,h=r.targetModifier;if(this.element=s,this.target=a,this.targetModifier=h,"viewport"===this.target?(this.target=document.body,this.targetModifier="visible"):"scroll-handle"===this.target&&(this.target=document.body,this.targetModifier="scroll-handle"),["element","target"].forEach(function(t){if("undefined"==typeof e[t])throw new Error("Tether Error: Both element and target must be defined");"undefined"!=typeof e[t].jquery?e[t]=e[t][0]:"string"==typeof e[t]&&(e[t]=document.querySelector(e[t]))}),l(this.element,this.getClass("element")),this.options.addTargetClasses!==!1&&l(this.target,this.getClass("target")),!this.options.attachment)throw new Error("Tether Error: You must provide an attachment");this.targetAttachment=j(this.options.targetAttachment),this.attachment=j(this.options.attachment),this.offset=X(this.options.offset),this.targetOffset=X(this.options.targetOffset),"undefined"!=typeof this.scrollParent&&this.disable(),this.scrollParent="scroll-handle"===this.targetModifier?this.target:n(this.target),this.options.enabled!==!1&&this.enable(o)}},{key:"getTargetBounds",value:function(){if("undefined"==typeof this.targetModifier)return r(this.target);if("visible"===this.targetModifier){if(this.target===document.body)return{top:pageYOffset,left:pageXOffset,height:innerHeight,width:innerWidth};var t=r(this.target),e={height:t.height,width:t.width,top:t.top,left:t.left};return e.height=Math.min(e.height,t.height-(pageYOffset-t.top)),e.height=Math.min(e.height,t.height-(t.top+t.height-(pageYOffset+innerHeight))),e.height=Math.min(innerHeight,e.height),e.height-=2,e.width=Math.min(e.width,t.width-(pageXOffset-t.left)),e.width=Math.min(e.width,t.width-(t.left+t.width-(pageXOffset+innerWidth))),e.width=Math.min(innerWidth,e.width),e.width-=2,e.topo.clientWidth||[i.overflow,i.overflowX].indexOf("scroll")>=0||this.target!==document.body,s=0;n&&(s=15);var a=t.height-parseFloat(i.borderTopWidth)-parseFloat(i.borderBottomWidth)-s,e={width:15,height:.975*a*(a/o.scrollHeight),left:t.left+t.width-parseFloat(i.borderLeftWidth)-15},f=0;408>a&&this.target===document.body&&(f=-11e-5*Math.pow(a,2)-.00727*a+22.58),this.target!==document.body&&(e.height=Math.max(e.height,24));var h=this.target.scrollTop/(o.scrollHeight-a);return e.top=h*(a-e.height-f)+t.top+parseFloat(i.borderTopWidth),this.target===document.body&&(e.height=Math.max(e.height,24)),e}}},{key:"clearCache",value:function(){this._cache={}}},{key:"cache",value:function(t,e){return"undefined"==typeof this._cache&&(this._cache={}),"undefined"==typeof this._cache[t]&&(this._cache[t]=e.call(this)),this._cache[t]}},{key:"enable",value:function(){var t=arguments.length<=0||void 0===arguments[0]?!0:arguments[0];this.options.addTargetClasses!==!1&&l(this.target,this.getClass("enabled")),l(this.element,this.getClass("enabled")),this.enabled=!0,this.scrollParent!==document&&this.scrollParent.addEventListener("scroll",this.position),t&&this.position()}},{key:"disable",value:function(){h(this.target,this.getClass("enabled")),h(this.element,this.getClass("enabled")),this.enabled=!1,"undefined"!=typeof this.scrollParent&&this.scrollParent.removeEventListener("scroll",this.position)}},{key:"destroy",value:function(){var t=this;this.disable(),B.forEach(function(e,o){return e===t?void B.splice(o,1):void 0})}},{key:"updateAttachClasses",value:function(t,e){var o=this;t=t||this.attachment,e=e||this.targetAttachment;var i=["left","top","bottom","right","middle","center"];"undefined"!=typeof this._addAttachClasses&&this._addAttachClasses.length&&this._addAttachClasses.splice(0,this._addAttachClasses.length),"undefined"==typeof this._addAttachClasses&&(this._addAttachClasses=[]);var n=this._addAttachClasses;t.top&&n.push(this.getClass("element-attached")+"-"+t.top),t.left&&n.push(this.getClass("element-attached")+"-"+t.left),e.top&&n.push(this.getClass("target-attached")+"-"+e.top),e.left&&n.push(this.getClass("target-attached")+"-"+e.left);var r=[];i.forEach(function(t){r.push(o.getClass("element-attached")+"-"+t),r.push(o.getClass("target-attached")+"-"+t)}),T(function(){"undefined"!=typeof o._addAttachClasses&&(c(o.element,o._addAttachClasses,r),o.options.addTargetClasses!==!1&&c(o.target,o._addAttachClasses,r),delete o._addAttachClasses)})}},{key:"position",value:function(){var t=this,e=arguments.length<=0||void 0===arguments[0]?!0:arguments[0];if(this.enabled){this.clearCache();var o=Y(this.targetAttachment,this.attachment);this.updateAttachClasses(this.attachment,o);var i=this.cache("element-bounds",function(){return r(t.element)}),n=i.width,f=i.height;if(0===n&&0===f&&"undefined"!=typeof this.lastSize){var h=this.lastSize;n=h.width,f=h.height}else this.lastSize={width:n,height:f};var l=this.cache("target-bounds",function(){return t.getTargetBounds()}),d=l,u=y(H(this.attachment),{width:n,height:f}),p=y(H(o),d),c=y(this.offset,{width:n,height:f}),g=y(this.targetOffset,d);u=v(u,c),p=v(p,g);for(var m=l.left+p.left-u.left,b=l.top+p.top-u.top,w=0;wwindow.innerWidth&&(A=this.cache("scrollbar-size",a),x.viewport.bottom-=A.height),document.body.scrollHeight>window.innerHeight&&(A=this.cache("scrollbar-size",a),x.viewport.right-=A.width),(-1===["","static"].indexOf(document.body.style.position)||-1===["","static"].indexOf(document.body.parentElement.style.position))&&(x.page.bottom=document.body.scrollHeight-b-f,x.page.right=document.body.scrollWidth-m-n),"undefined"!=typeof this.options.optimizations&&this.options.optimizations.moveElement!==!1&&"undefined"==typeof this.targetModifier&&!function(){var e=t.cache("target-offsetparent",function(){return s(t.target)}),o=t.cache("target-offsetparent-bounds",function(){return r(e)}),i=getComputedStyle(e),n=o,a={};if(["Top","Left","Bottom","Right"].forEach(function(t){a[t.toLowerCase()]=parseFloat(i["border"+t+"Width"])}),o.right=document.body.scrollWidth-o.left-n.width+a.right,o.bottom=document.body.scrollHeight-o.top-n.height+a.bottom,x.page.top>=o.top+a.top&&x.page.bottom>=o.bottom&&x.page.left>=o.left+a.left&&x.page.right>=o.right){var f=e.scrollTop,h=e.scrollLeft;x.offset={top:x.page.top-o.top+f-a.top,left:x.page.left-o.left+h-a.left}}}(),this.move(x),this.history.unshift(x),this.history.length>3&&this.history.pop(),e&&S(),!0}}},{key:"move",value:function(t){var e=this;if("undefined"!=typeof this.element.parentNode){var o={};for(var i in t){o[i]={};for(var n in t[i]){for(var r=!1,a=0;a=0&&(b=parseFloat(b),y=parseFloat(y)),b!==y&&(v=!0,m[n]=y)}v&&T(function(){f(e.element.style,m)})}}}]),t}();N.modules=[],C.position=_;var R=f(N,C),M=function(){function t(t,e){var o=[],i=!0,n=!1,r=void 0;try{for(var s,a=t[Symbol.iterator]();!(i=(s=a.next()).done)&&(o.push(s.value),!e||o.length!==e);i=!0);}catch(f){n=!0,r=f}finally{try{!i&&a["return"]&&a["return"]()}finally{if(n)throw r}}return o}return function(e,o){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,o);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),P=C.Utils,r=P.getBounds,f=P.extend,c=P.updateClasses,T=P.defer,U=["left","top","right","bottom"];C.modules.push({position:function(t){var e=this,o=t.top,i=t.left,n=t.targetAttachment;if(!this.options.constraints)return!0;var s=this.cache("element-bounds",function(){return r(e.element)}),a=s.height,h=s.width;if(0===h&&0===a&&"undefined"!=typeof this.lastSize){var l=this.lastSize;h=l.width,a=l.height}var d=this.cache("target-bounds",function(){return e.getTargetBounds()}),u=d.height,p=d.width,g=[this.getClass("pinned"),this.getClass("out-of-bounds")];this.options.constraints.forEach(function(t){var e=t.outOfBoundsClass,o=t.pinnedClass;e&&g.push(e),o&&g.push(o)}),g.forEach(function(t){["left","top","right","bottom"].forEach(function(e){g.push(t+"-"+e)})});var m=[],v=f({},n),y=f({},this.attachment);return this.options.constraints.forEach(function(t){var r=t.to,s=t.attachment,f=t.pin;"undefined"==typeof s&&(s="");var l=void 0,d=void 0;if(s.indexOf(" ")>=0){var c=s.split(" "),g=M(c,2);d=g[0],l=g[1]}else l=d=s;var w=b(e,r);("target"===d||"both"===d)&&(ow[3]&&"bottom"===v.top&&(o-=u,v.top="top")),"together"===d&&(ow[3]&&"bottom"===v.top&&("top"===y.top?(o-=u,v.top="top",o-=a,y.top="bottom"):"bottom"===y.top&&(o-=u,v.top="top",o+=a,y.top="top")),"middle"===v.top&&(o+a>w[3]&&"top"===y.top?(o-=a,y.top="bottom"):ow[2]&&"right"===v.left&&(i-=p,v.left="left")),"together"===l&&(iw[2]&&"right"===v.left?"left"===y.left?(i-=p,v.left="left",i-=h,y.left="right"):"right"===y.left&&(i-=p,v.left="left",i+=h,y.left="left"):"center"===v.left&&(i+h>w[2]&&"left"===y.left?(i-=h,y.left="right"):iw[3]&&"top"===y.top&&(o-=a,y.top="bottom")),("element"===l||"both"===l)&&(iw[2]&&"left"===y.left&&(i-=h,y.left="right")),"string"==typeof f?f=f.split(",").map(function(t){return t.trim()}):f===!0&&(f=["top","left","right","bottom"]),f=f||[];var C=[],O=[];o=0?(o=w[1],C.push("top")):O.push("top")),o+a>w[3]&&(f.indexOf("bottom")>=0?(o=w[3]-a,C.push("bottom")):O.push("bottom")),i=0?(i=w[0],C.push("left")):O.push("left")),i+h>w[2]&&(f.indexOf("right")>=0?(i=w[2]-h,C.push("right")):O.push("right")),C.length&&!function(){var t=void 0;t="undefined"!=typeof e.options.pinnedClass?e.options.pinnedClass:e.getClass("pinned"),m.push(t),C.forEach(function(e){m.push(t+"-"+e)})}(),O.length&&!function(){var t=void 0;t="undefined"!=typeof e.options.outOfBoundsClass?e.options.outOfBoundsClass:e.getClass("out-of-bounds"),m.push(t),O.forEach(function(e){m.push(t+"-"+e)})}(),(C.indexOf("left")>=0||C.indexOf("right")>=0)&&(y.left=v.left=!1),(C.indexOf("top")>=0||C.indexOf("bottom")>=0)&&(y.top=v.top=!1),(v.top!==n.top||v.left!==n.left||y.top!==e.attachment.top||y.left!==e.attachment.left)&&e.updateAttachClasses(y,v)}),T(function(){e.options.addTargetClasses!==!1&&c(e.target,m,g),c(e.element,m,g)}),{top:o,left:i}}});var P=C.Utils,r=P.getBounds,c=P.updateClasses,T=P.defer;C.modules.push({position:function(t){var e=this,o=t.top,i=t.left,n=this.cache("element-bounds",function(){return r(e.element)}),s=n.height,a=n.width,f=this.getTargetBounds(),h=o+s,l=i+a,d=[];o<=f.bottom&&h>=f.top&&["left","right"].forEach(function(t){var e=f[t];(e===i||e===l)&&d.push(t)}),i<=f.right&&l>=f.left&&["top","bottom"].forEach(function(t){var e=f[t];(e===o||e===h)&&d.push(t)});var u=[],p=[],g=["left","top","right","bottom"];return u.push(this.getClass("abutted")),g.forEach(function(t){u.push(e.getClass("abutted")+"-"+t)}),d.length&&p.push(this.getClass("abutted")),d.forEach(function(t){p.push(e.getClass("abutted")+"-"+t)}),T(function(){e.options.addTargetClasses!==!1&&c(e.target,p,u),c(e.element,p,u)}),!0}});var M=function(){function t(t,e){var o=[],i=!0,n=!1,r=void 0;try{for(var s,a=t[Symbol.iterator]();!(i=(s=a.next()).done)&&(o.push(s.value),!e||o.length!==e);i=!0);}catch(f){n=!0,r=f}finally{try{!i&&a["return"]&&a["return"]()}finally{if(n)throw r}}return o}return function(e,o){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,o);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();return C.modules.push({position:function(t){var e=t.top,o=t.left;if(this.options.shift){var i=this.options.shift;"function"==typeof this.options.shift&&(i=this.options.shift.call(this,{top:e,left:o}));var n=void 0,r=void 0;if("string"==typeof i){i=i.split(" "),i[1]=i[1]||i[0];var s=M(i,2);n=s[0],r=s[1],n=parseFloat(n,10),r=parseFloat(r,10)}else n=i.top,r=i.left;return e+=n,o+=r,{top:e,left:o}}}}),R}); -} \ No newline at end of file diff --git a/examples/examples/js/ui/ui.extra.js b/examples/examples/js/ui/ui.extra.js deleted file mode 100644 index 602c27602..000000000 --- a/examples/examples/js/ui/ui.extra.js +++ /dev/null @@ -1,1136 +0,0 @@ -/** - * @author Alexander Rose - */ - -// Html - -UI.Html = function (html) { - UI.Element.call(this) - - var dom = document.createElement('span') - dom.className = 'Html' - dom.style.cursor = 'default' - dom.style.display = 'inline-block' - dom.style.verticalAlign = 'middle' - - this.dom = dom - this.setValue(html) - - return this -} - -UI.Html.prototype = Object.create(UI.Element.prototype) - -UI.Html.prototype.setValue = function (value) { - if (value !== undefined) { - this.dom.innerHTML = value - } - - return this -} - -// Form - -UI.Form = function () { - UI.Panel.call(this) - - var dom = document.createElement('form') - dom.className = 'Form' - dom.method = 'post' - dom.action = '' - dom.target = '_blank' - dom.enctype = 'multipart/form-data' - - this.dom = dom - - return this -} - -UI.Form.prototype = Object.create(UI.Panel.prototype) - -UI.Form.prototype.setMethod = function (value) { - this.dom.method = value - - return this -} - -UI.Form.prototype.setAction = function (value) { - this.dom.action = value - - return this -} - -UI.Form.prototype.setTarget = function (value) { - this.dom.target = value - - return this -} - -UI.Form.prototype.setEnctype = function (value) { - this.dom.enctype = value - - return this -} - -// File - -UI.File = function () { - UI.Input.call(this) - - this.dom.className = 'File' - this.dom.type = 'file' - this.dom.multiple = false - - return this -} - -UI.File.prototype = Object.create(UI.Input.prototype) - -UI.File.prototype.setMultiple = function (value) { - this.dom.multiple = value - - return this -} - -UI.File.prototype.getFiles = function (value) { - return this.dom.files -} - -// Hidden - -UI.Hidden = function () { - UI.Input.call(this) - - this.dom.type = 'hidden' - - return this -} - -UI.Hidden.prototype = Object.create(UI.Input.prototype) - -// Toggle Button - -UI.ToggleButton = function (labelA, labelB, callbackA, callbackB) { - UI.Button.call(this, labelB) - - var flag = true - - this.onClick(function () { - if (flag) { - flag = false - this.setLabel(labelA) - callbackB() - } else { - flag = true - this.setLabel(labelB) - callbackA() - } - }.bind(this)) - - return this -} - -UI.ToggleButton.prototype = Object.create(UI.Button.prototype) - -// Ellipsis Text - -UI.EllipsisText = function (text) { - UI.Text.call(this, text) - - this.setWhiteSpace('nowrap') - this.setOverflow('hidden') - this.setTextOverflow('ellipsis') - - return this -} - -UI.EllipsisText.prototype = Object.create(UI.Text.prototype) - -UI.EllipsisText.prototype.setValue = function (value) { - if (value !== undefined) { - this.dom.textContent = value - this.setTitle(value) - } - - return this -} - -// Ellipsis Multiline Text - -UI.EllipsisMultilineText = function (text) { - // http://www.mobify.com/blog/multiline-ellipsis-in-pure-css/ - - UI.Element.call(this) - - var dom = document.createElement('span') - dom.className = 'EllipsisMultilineText' - dom.style.cursor = 'default' - dom.style.display = 'inline-block' - dom.style.verticalAlign = 'middle' - - var content = document.createElement('p') - dom.appendChild(content) - - this.dom = dom - this.content = content - - this.setValue(text) - - return this -} - -UI.EllipsisMultilineText.prototype = Object.create(UI.Element.prototype) - -UI.EllipsisMultilineText.prototype.setValue = function (value) { - if (value !== undefined) { - this.content.textContent = value - this.setTitle(value) - } - - return this -} - -// Overlay Panel - -UI.OverlayPanel = function () { - UI.Panel.call(this) - - this.dom.className = 'Panel OverlayPanel' - this.dom.tabIndex = '-1' - this.dom.style.outline = 'none' - - return this -} - -UI.OverlayPanel.prototype = Object.create(UI.Panel.prototype) - -UI.OverlayPanel.prototype.attach = function (node) { - node = node || document.body - - node.appendChild(this.dom) - - return this -} - -// Icon (requires font awesome) - -UI.Icon = function (value) { - UI.Panel.call(this) - - var dom = document.createElement('span') - dom.className = 'Icon fa' - - this.dom = dom - - if (value) this.addClass.apply(this, arguments) - - return this -} - -UI.Icon.prototype = Object.create(UI.Panel.prototype) - -UI.Icon.prototype.hasClass = function (value) { - return this.dom.classList.contains('fa-' + value) -} - -UI.Icon.prototype.addClass = function (value) { - for (var i = 0; i < arguments.length; i++) { - this.dom.classList.add('fa-' + arguments[ i ]) - } - - return this -} - -UI.Icon.prototype.setClass = function (value) { - this.dom.className = 'Icon fa' - - for (var i = 0; i < arguments.length; i++) { - this.dom.classList.add('fa-' + arguments[ i ]) - } - - return this -} - -UI.Icon.prototype.removeClass = function (value) { - for (var i = 0; i < arguments.length; i++) { - this.dom.classList.remove('fa-' + arguments[ i ]) - } - - return this -} - -UI.Icon.prototype.switchClass = function (newValue, oldValue) { - this.removeClass(oldValue, newValue) - this.addClass(newValue) - - return this -} - -// Toggle Icon - -UI.ToggleIcon = function (value, classTrue, classFalse) { - UI.Icon.call(this, value ? classTrue : classFalse) - - this.value = value - this.classTrue = classTrue - this.classFalse = classFalse - - return this -} - -UI.ToggleIcon.prototype = Object.create(UI.Icon.prototype) - -UI.ToggleIcon.prototype.setValue = function (value) { - this.value = value - - if (value) { - this.switchClass(this.classTrue, this.classFalse) - } else { - this.switchClass(this.classFalse, this.classTrue) - } - - return this -} - -UI.ToggleIcon.prototype.getValue = function () { - return this.value -} - -// Dispose Icon - -UI.DisposeIcon = function () { - UI.Icon.call(this, 'trash-o') - - var flag = false - var scope = this - - this.setTitle('delete') - this.setCursor('pointer') - - this.onClick(function () { - if (flag === true) { - if (typeof scope.disposeFunction === 'function') { - scope.disposeFunction() - } - } else { - scope.setColor('rgb(178, 34, 34)') - scope.dom.classList.add('deleteInfo') - flag = true - - setTimeout(function () { - scope.setColor('#888') - scope.dom.classList.remove('deleteInfo') - flag = false - }, 1500) - } - }) - - return this -} - -UI.DisposeIcon.prototype = Object.create(UI.Icon.prototype) - -UI.DisposeIcon.prototype.setDisposeFunction = function (fn) { - this.disposeFunction = fn - - return this -} - -// Progress - -UI.Progress = function (max, value) { - UI.Element.call(this) - - var dom = document.createElement('progress') - dom.className = 'Progress' - - dom.max = max || 1.0 - if (value !== undefined) dom.value = value - - this.dom = dom - - return this -} - -UI.Progress.prototype = Object.create(UI.Element.prototype) - -UI.Progress.prototype.getValue = function () { - return this.dom.value -} - -UI.Progress.prototype.setValue = function (value) { - this.dom.value = value - - return this -} - -UI.Progress.prototype.setMax = function (value) { - this.dom.max = value - - return this -} - -UI.Progress.prototype.setIndeterminate = function () { - this.dom.removeAttribute('value') - - return this -} - -// Range - -UI.Range = function (min, max, value, step) { - UI.Element.call(this) - - var dom = document.createElement('input') - dom.className = 'Range' - dom.type = 'range' - - dom.min = min.toPrecision(3) - dom.max = max.toPrecision(3) - dom.value = value.toPrecision(3) - dom.step = step.toPrecision(3) - - this.dom = dom - - return this -} - -UI.Range.prototype = Object.create(UI.Element.prototype) - -UI.Range.prototype.getValue = function () { - return parseFloat(this.dom.value) -} - -UI.Range.prototype.setRange = function (min, max) { - this.dom.min = min - this.dom.max = max - - return this -} - -UI.Range.prototype.setValue = function (value) { - this.dom.value = value - - return this -} - -UI.Range.prototype.setStep = function (value) { - this.dom.step = value - - return this -} - -// AdaptiveTextArea - -UI.AdaptiveTextArea = function () { - // http://www.brianchu.com/blog/2013/11/02/creating-an-auto-growing-text-input/ - - UI.Element.call(this) - - var container = document.createElement('div') - container.className = 'AdaptiveTextAreaContainer' - - var textarea = document.createElement('textarea') - textarea.className = 'AdaptiveTextArea' - - var size = document.createElement('div') - size.className = 'AdaptiveTextAreaSize' - - container.appendChild(textarea) - container.appendChild(size) - - textarea.addEventListener('input', function (event) { - size.innerHTML = textarea.value + '\n' - }, false) - - this.textarea = textarea - this.size = size - this.dom = container - - return this -} - -UI.AdaptiveTextArea.prototype = Object.create(UI.Element.prototype) - -UI.AdaptiveTextArea.prototype.getValue = function () { - return this.textarea.value -} - -UI.AdaptiveTextArea.prototype.setValue = function (value) { - this.textarea.value = value - this.size.innerHTML = value + '\n' - - return this -} - -UI.AdaptiveTextArea.prototype.setSpellcheck = function (value) { - this.textarea.spellcheck = value - - return this -} - -UI.AdaptiveTextArea.prototype.setBackgroundColor = function (value) { - this.textarea.style.backgroundColor = value - - return this -} - -// Virtual List - -UI.VirtualList = function (items, itemHeight, height, generatorFn) { - // based on Virtual DOM List - // https://github.com/sergi/virtual-list - // The MIT License (MIT) - // Copyright (C) 2013 Sergi Mansilla - - UI.Element.call(this) - - items = items || [] - itemHeight = itemHeight || 20 - height = height || 300 - generatorFn = generatorFn || function () {} - - var dom = document.createElement('div') - dom.className = 'VirtualList' - dom.style.height = height + 'px' - - var totalRows = items.length - var screenItemsCount = Math.ceil(height / itemHeight) - var cachedItemsCount = screenItemsCount * 3 - var lastRepaintY - var maxBuffer = screenItemsCount * itemHeight - var lastScrolled = 0 - var renderChunkCallback = function () {} - - var list = document.createElement('div') - list.style.width = '100%' - list.style.height = height + 'px' - list.style[ 'overflow-y' ] = 'auto' - list.style.position = 'relative' - list.style.padding = 0 - - var scroller = document.createElement('div') - scroller.style.opacity = 0 - scroller.style.position = 'absolute' - scroller.style.top = 0 - scroller.style.left = 0 - scroller.style.width = '1px' - scroller.style.height = (itemHeight * totalRows) + 'px' - - function createRow (i) { - var item = generatorFn(i) - item.classList.add('VirtualListRow') - item.style.height = itemHeight + 'px' - item.style.top = (i * itemHeight) + 'px' - return item - } - - function renderChunk (from) { - var finalItem = Math.min(totalRows, from + cachedItemsCount) - renderChunkCallback(from, finalItem) - // Append all the new rows in a document fragment - // that we will later append to the parent node - var fragment = document.createDocumentFragment() - for (var i = from; i < finalItem; i++) { - fragment.appendChild(createRow(i)) - } - // Hide and mark obsolete nodes for deletion. - for (var j = 1, l = list.childNodes.length; j < l; j++) { - list.childNodes[ j ].style.display = 'none' - list.childNodes[ j ].setAttribute('data-rm', '1') - } - list.appendChild(fragment) - }; - - // As soon as scrolling has stopped, this interval asynchronously - // removes all the nodes that are not used anymore - var rmNodeInterval = setInterval(function () { - // check if list is still attached to dom - var element = dom - while (element !== document && element.parentNode) { - element = element.parentNode - } - // if list not attached to dom, clear interval - if (element !== document) { - clearInterval(rmNodeInterval) - } - // remove tagged nodes - if (Date.now() - lastScrolled > 100) { - var badNodes = list.querySelectorAll('[data-rm="1"]') - for (var i = 0, l = badNodes.length; i < l; i++) { - list.removeChild(badNodes[ i ]) - } - } - }, 500) - - function onScroll (e) { - var scrollTop = e.target.scrollTop // Triggers reflow - if (!lastRepaintY || Math.abs(scrollTop - lastRepaintY) > maxBuffer) { - var first = Math.floor(scrollTop / itemHeight) - renderChunk(Math.max(0, first - screenItemsCount)) - lastRepaintY = scrollTop - } - lastScrolled = Date.now() - e.preventDefault && e.preventDefault() - } - - // API - - this.setItems = function (value) { - items = value - totalRows = items.length - scroller.style.height = (itemHeight * totalRows) + 'px' - renderChunk(0) - return this - } - - this.setItemHeight = function (value) { - itemHeight = value - screenItemsCount = Math.ceil(height / itemHeight) - cachedItemsCount = screenItemsCount * 3 - maxBuffer = screenItemsCount * itemHeight - scroller.style.height = (itemHeight * totalRows) + 'px' - renderChunk(0) - return this - } - - this.setHeight = function (value) { - UI.Element.prototype.setHeight.call(this, value + 'px') - height = value - screenItemsCount = Math.ceil(height / itemHeight) - cachedItemsCount = screenItemsCount * 3 - maxBuffer = screenItemsCount * itemHeight - list.style.height = height + 'px' - scroller.style.height = height + 'px' - renderChunk(0) - return this - } - - this.setGeneratorFn = function (value) { - generatorFn = value - renderChunk(0) - return this - } - - this.setRenderChunkCallback = function (value) { - renderChunkCallback = value - } - - this.redraw = function () { - var first = Math.floor(list.scrollTop / itemHeight) - renderChunk(Math.max(0, first - screenItemsCount)) - lastRepaintY = list.scrollTop - return this - } - - // - - list.appendChild(scroller) - dom.appendChild(list) - list.addEventListener('scroll', onScroll) - renderChunk(0) - - this.dom = dom - - return this -} - -UI.VirtualList.prototype = Object.create(UI.Element.prototype) - -// Virtual Table - -UI.VirtualTable = function (items, itemHeight, height, columns, params) { - var p = params || {} - - UI.Panel.call(this) - - // this.setOverflow( "scroll" ); - - var defaultWidth = p.defaultWidth !== undefined ? p.defaultWidth : 30 - var defaultMargin = p.defaultMargin !== undefined ? p.defaultMargin : 5 - var defaultAlign = p.defaultAlign !== undefined ? p.defaultAlign : 'left' - var onRowSelect = p.onRowSelect - - // header - - var header = new UI.Panel() - .setWhiteSpace('nowrap') - .setDisplay('inline-block') - .setOverflow('') - .setWidth('100%') - - var fullWidth = 0 - - var selected = [] - - var numericalSort = function (a, b) { - return a - b - } - - var lexicalSort = function (a, b) { - return a.localeCompare(b) - } - - var sortColumn = function (idx, flag) { - var sort - if (typeof items[ 0 ][ idx ] === 'string') { - sort = lexicalSort - } else { - sort = numericalSort - } - items.sort(function (a, b) { - if (flag) { - return sort(b[ idx ], a[ idx ]) - } else { - return sort(a[ idx ], b[ idx ]) - } - }) - virtualList.redraw() - return this - } - - var selectRow = function (event, idx) { - selected.length = 0 - if (onRowSelect) onRowSelect(event, idx) - if (idx !== undefined) { - selected.push(items[ idx ][ 0 ]) - } - virtualList.redraw() - return this - } - - columns.forEach(function (col) { - var width = col.width || defaultWidth - var margin = col.margin || defaultMargin - - var text = new UI.EllipsisText() - .setValue(col.name) - .setWidth(width + 'px') - .setTextAlign(col.align || defaultAlign) - .setMarginLeft(margin + 'px') - .setMarginRight(margin + 'px') - .setCursor('pointer') - .onClick(function (e) { - var flag = col.__sortFlag === 'ASC' - sortColumn(col.index, flag) - if (flag) { - col.__sortFlag = 'DESC' - } else { - col.__sortFlag = 'ASC' - } - }) - - header.add(text) - - fullWidth += width + 2 * margin - }) - - // list - - var generatorFn = function (index) { - var panel = new UI.Panel() - - columns.forEach(function (col) { - var value = items[ index ][ col.index ] - if (col.format) value = col.format(value) - - var width = col.width || defaultWidth - var margin = col.margin || defaultMargin - - var element - if (typeof value === 'object') { - element = value - } else { - element = new UI.Text() - .setValue(value) - } - - element - .setWidth(width + 'px') - .setTextAlign(col.align || defaultAlign) - .setMarginLeft(margin + 'px') - .setMarginRight(margin + 'px') - .onClick(function (event) { - if (typeof col.onClick === 'function') { - col.onClick(event, index, value) - } - }) - .onMouseOver(function (event) { - if (typeof col.onMouseOver === 'function') { - col.onMouseOver(event, index, value) - } - }) - .onMouseOut(function (event) { - if (typeof col.onMouseOut === 'function') { - col.onMouseOut(event, index, value) - } - }) - - panel.add(element) - }) - - panel - .setCursor('pointer') - .onClick(function (event) { - selectRow(event, index) - }) - - if (selected.indexOf(items[ index ][ 0 ]) !== -1) { - panel.dom.classList.add('highlight') - } - - return panel.dom - } - - var virtualList = new UI.VirtualList( - items, itemHeight, height, generatorFn - ).setWidth((fullWidth + 20) + 'px') - - // - - this.add(header, virtualList) - - // API - - this.header = header - this.list = virtualList - this.sortColumn = sortColumn - this.selectRow = function (idx) { - selectRow(undefined, idx) - } - - return this -} - -UI.VirtualTable.prototype = Object.create(UI.Panel.prototype) - -// Popup Menu (requires Tether) - -UI.PopupMenu = function (iconClass, heading, constraintTo) { - constraintTo = constraintTo || 'scrollParent' - - UI.Panel.call(this) - - var entryLabelWidth = '100px' - - var icon = new UI.Icon(iconClass || 'bars') - - var panel = new UI.OverlayPanel() - .setDisplay('none') - .attach(this.dom) - - var xOffset = 0 - var yOffset = 0 - - var prevX = 0 - var prevY = 0 - - function onMousemove (e) { - if (prevX === 0) { - prevX = e.clientX - prevY = e.clientY - } - xOffset += prevX - e.clientX - yOffset += prevY - e.clientY - prevX = e.clientX - prevY = e.clientY - tether.setOptions({ - element: panel.dom, - target: icon.dom, - attachment: 'top right', - targetAttachment: 'top left', - offset: yOffset + 'px ' + xOffset + 'px', - constraints: [{ - to: constraintTo, - pin: ['top', 'bottom'] - }] - }) - tether.position() - } - - var headingPanel = new UI.Panel() - .setBorderBottom('1px solid #555') - .setMarginBottom('10px') - .setHeight('25px') - .setCursor('move') - .onMouseDown(function (e) { - if (e.which === 1) { - document.addEventListener('mousemove', onMousemove) - } - document.addEventListener('mouseup', function (e) { - document.removeEventListener('mousemove', onMousemove) - }) - }) - - headingPanel - .add( - new UI.Icon('times') - .setFloat('right') - .setCursor('pointer') - .onClick(function () { - this.setMenuDisplay('none') - }.bind(this)) - ) - .add( - new UI.Text(heading) - ) - - panel.add(headingPanel) - - var tether - - icon.setTitle('menu') - icon.setCursor('pointer') - icon.onClick(function (e) { - if (panel.getDisplay() === 'block') { - this.setMenuDisplay('none') - tether.destroy() - return - } - - panel.setMaxHeight((window.innerHeight / 1.2) + 'px') - this.setMenuDisplay('block') - - xOffset = 5 - yOffset = 0 - - tether = new Tether({ - element: panel.dom, - target: icon.dom, - attachment: 'top right', - targetAttachment: 'top left', - offset: '0px 5px', - constraints: [{ - to: constraintTo, - attachment: 'element', - pin: ['top', 'bottom'] - }] - }) - - tether.position() - }.bind(this)) - - this.add(icon) - - this.setClass('') - .setDisplay('inline') - - this.icon = icon - this.panel = panel - this.entryLabelWidth = entryLabelWidth - - return this -} - -UI.PopupMenu.prototype = Object.create(UI.Panel.prototype) - -UI.PopupMenu.prototype.addEntry = function (label, entry) { - this.panel - .add(new UI.Text(label) - // .setWhiteSpace( "nowrap" ) - .setWidth(this.entryLabelWidth)) - .add(entry || new UI.Panel()) - .add(new UI.Break()) - - return this -} - -UI.PopupMenu.prototype.setEntryLabelWidth = function (value) { - this.entryLabelWidth = value - - return this -} - -UI.PopupMenu.prototype.setMenuDisplay = function (value) { - this.panel.setDisplay(value) - - if (value !== 'none') this.panel.dom.focus() - - return this -} - -UI.PopupMenu.prototype.setIconTitle = function (value) { - this.icon.setTitle(value) - - return this -} - -UI.PopupMenu.prototype.dispose = function () { - this.panel.dispose() - - UI.Element.prototype.dispose.call(this) -} - -// Collapsible Icon Panel - -UI.CollapsibleIconPanel = function (iconClass1, iconClass2) { - UI.Panel.call(this) - - this.dom.className = 'Panel CollapsiblePanel' - - if (iconClass1 === undefined) { - // iconClass1 = iconClass1 || "plus-square"; - // iconClass2 = iconClass2 || "minus-square"; - - iconClass1 = iconClass1 || 'chevron-down' - iconClass2 = iconClass2 || 'chevron-right' - } - - this.button = new UI.Icon(iconClass1) - .setTitle('expand/collapse') - .setCursor('pointer') - .setWidth('12px') - .setMarginRight('6px') - this.addStatic(this.button) - - var scope = this - this.button.dom.addEventListener('click', function (event) { - scope.toggle() - }, false) - - this.content = document.createElement('div') - this.content.className = 'CollapsibleContent' - this.dom.appendChild(this.content) - - this.isCollapsed = false - - this.iconClass1 = iconClass1 - this.iconClass2 = iconClass2 - - return this -} - -UI.CollapsibleIconPanel.prototype = Object.create(UI.CollapsiblePanel.prototype) - -UI.CollapsibleIconPanel.prototype.setCollapsed = function (setCollapsed) { - if (setCollapsed) { - this.dom.classList.add('collapsed') - - if (this.iconClass2) { - this.button.switchClass(this.iconClass2, this.iconClass1) - } else { - this.button.addClass('rotate-90') - } - } else { - this.dom.classList.remove('collapsed') - - if (this.iconClass2) { - this.button.switchClass(this.iconClass1, this.iconClass2) - } else { - this.button.removeClass('rotate-90') - } - } - - this.isCollapsed = setCollapsed -} - -// Color picker (requires FlexiColorPicker) -// https://github.com/DavidDurman/FlexiColorPicker -// https://github.com/zvin/FlexiColorPicker - -UI.ColorPicker = function () { - var scope = this - - UI.Panel.call(this) - - // slider - - this.slideWrapper = new UI.Panel() - .setClass('slide-wrapper') - - this.sliderIndicator = new UI.Panel() - .setClass('slide-indicator') - - this.slider = new UI.Panel() - .setClass('slide') - .setWidth('25px') - .setHeight('80px') - - this.slideWrapper.add( - this.slider, - this.sliderIndicator - ) - - // picker - - this.pickerWrapper = new UI.Panel() - .setClass('picker-wrapper') - - this.pickerIndicator = new UI.Panel() - .setClass('picker-indicator') - - this.picker = new UI.Panel() - .setClass('picker') - .setWidth('130px') - .setHeight('80px') - - this.pickerWrapper.add( - this.picker, - this.pickerIndicator - ) - - // event - - var changeEvent = document.createEvent('Event') - changeEvent.initEvent('change', true, true) - - // finalize - - this.add( - this.pickerWrapper, - this.slideWrapper - ) - - this.colorPicker = ColorPicker( - - this.slider.dom, - this.picker.dom, - - function (hex, hsv, rgb, pickerCoordinate, sliderCoordinate) { - if (!pickerCoordinate && sliderCoordinate && hsv.s < 0.05) { - hsv.s = 0.5 - hsv.v = 0.7 - scope.colorPicker.setHsv(hsv) - - return - } - - ColorPicker.positionIndicators( - scope.sliderIndicator.dom, scope.pickerIndicator.dom, - sliderCoordinate, pickerCoordinate - ) - - scope.hex = hex - scope.hsv = hsv - scope.rgb = rgb - - if (!scope._settingValue) { - scope.dom.dispatchEvent(changeEvent) - } - } - - ) - - this.colorPicker.fixIndicators( - this.sliderIndicator.dom, - this.pickerIndicator.dom - ) - - return this -} - -UI.ColorPicker.prototype = Object.create(UI.Panel.prototype) - -UI.ColorPicker.prototype.setValue = function (value) { - if (value !== this.hex) { - this._settingValue = true - this.colorPicker.setHex(value) - this._settingValue = false - } - - return this -} - -UI.ColorPicker.prototype.getValue = function () { - return this.hex -} diff --git a/examples/examples/js/ui/ui.js b/examples/examples/js/ui/ui.js deleted file mode 100644 index 241eca598..000000000 --- a/examples/examples/js/ui/ui.js +++ /dev/null @@ -1,1037 +0,0 @@ -/** - * @author mrdoob / http://mrdoob.com/ - * The MIT License, Copyright © 2010-2016 three.js authors - */ - -// TODO changes by Alexander S. Rose -// - more events and properties -// - ctrlKey modifier for Number and Integer -// - UI.Element.prototype.getBox() -// - UI.Element.prototype.dispose() -// - UI.Element.prototype.setTitle() -// - UI.Element.prototype.getStyle() - -var UI = {} - -UI.Element = function () {} - -UI.Element.prototype = { - - setId: function (id) { - this.dom.id = id - - return this - }, - - setTitle: function (title) { - this.dom.title = title - - return this - }, - - setClass: function (name) { - this.dom.className = name - - return this - }, - - setStyle: function (style, array) { - for (var i = 0; i < array.length; i++) { - this.dom.style[ style ] = array[ i ] - } - }, - - getStyle: function (style) { - return this.dom.style[ style ] - }, - - getBox: function () { - return this.dom.getBoundingClientRect() - }, - - setDisabled: function (value) { - this.dom.disabled = value - - return this - }, - - setTextContent: function (value) { - this.dom.textContent = value - - return this - }, - - dispose: function () { - this.dom.parentNode.removeChild(this.dom) - } - -} - -// properties - -var properties = [ - 'position', 'left', 'top', 'right', 'bottom', 'width', 'height', 'border', - 'borderLeft', 'borderTop', 'borderRight', 'borderBottom', 'borderColor', - 'display', 'overflow', 'overflowX', 'overflowY', 'margin', 'marginLeft', - 'marginTop', 'marginRight', - 'marginBottom', 'padding', 'paddingLeft', 'paddingTop', 'paddingRight', - 'paddingBottom', 'color', 'backgroundColor', 'opacity', 'fontSize', - 'fontWeight', 'fontStyle', 'fontFamily', 'textTransform', 'cursor', - 'verticalAlign', 'clear', 'float', 'zIndex', 'minHeight', 'maxHeight', - 'minWidth', 'maxWidth', 'wordBreak', 'wordWrap', 'spellcheck', - 'lineHeight', 'whiteSpace', 'textOverflow', 'textAlign', 'pointerEvents' -] - -properties.forEach(function (property) { - var methodSuffix = property.substr(0, 1).toUpperCase() + - property.substr(1, property.length) - - UI.Element.prototype[ 'set' + methodSuffix ] = function () { - this.setStyle(property, arguments) - return this - } - - UI.Element.prototype[ 'get' + methodSuffix ] = function () { - return this.getStyle(property) - } -}) - -// events - -var events = [ - 'KeyUp', 'KeyDown', 'KeyPress', - 'MouseOver', 'MouseOut', 'MouseDown', 'MouseUp', 'MouseMove', - 'Click', 'Change', 'Input', 'Scroll' -] - -events.forEach(function (event) { - var method = 'on' + event - - UI.Element.prototype[ method ] = function (callback) { - this.dom.addEventListener(event.toLowerCase(), callback.bind(this), false) - - return this - } -}) - -// Panel - -UI.Panel = function () { - UI.Element.call(this) - - var dom = document.createElement('div') - dom.className = 'Panel' - - this.dom = dom - this.children = [] - - return this -} - -UI.Panel.prototype = Object.create(UI.Element.prototype) - -UI.Panel.prototype.add = function () { - for (var i = 0; i < arguments.length; i++) { - this.dom.appendChild(arguments[ i ].dom) - this.children.push(arguments[ i ]) - } - - return this -} - -UI.Panel.prototype.remove = function () { - for (var i = 0; i < arguments.length; i++) { - this.dom.removeChild(arguments[ i ].dom) - - var idx = this.children.indexOf(arguments[ i ]) - if (idx !== -1) this.children.splice(idx, 1) - } - - return this -} - -UI.Panel.prototype.clear = function () { - while (this.dom.children.length) { - this.dom.removeChild(this.dom.lastChild) - } - - this.children.length = 0 - - return this -} - -// Collapsible Panel - -UI.CollapsiblePanel = function () { - UI.Panel.call(this) - - this.dom.className = 'Panel CollapsiblePanel' - - this.button = document.createElement('div') - this.button.className = 'CollapsiblePanelButton' - this.dom.appendChild(this.button) - - var scope = this - this.button.addEventListener('click', function (event) { - scope.toggle() - }, false) - - this.content = document.createElement('div') - this.content.className = 'CollapsibleContent' - this.dom.appendChild(this.content) - - this.isCollapsed = false - - return this -} - -UI.CollapsiblePanel.prototype = Object.create(UI.Panel.prototype) - -UI.CollapsiblePanel.prototype.addStatic = function () { - for (var i = 0; i < arguments.length; i++) { - this.dom.insertBefore(arguments[ i ].dom, this.content) - } - - return this -} - -UI.CollapsiblePanel.prototype.removeStatic = UI.Panel.prototype.remove - -UI.CollapsiblePanel.prototype.clearStatic = function () { - this.dom.childNodes.forEach(function (child) { - if (child !== this.content) { - this.dom.removeChild(child) - } - }) -} - -UI.CollapsiblePanel.prototype.add = function () { - for (var i = 0; i < arguments.length; i++) { - this.content.appendChild(arguments[ i ].dom) - } - - return this -} - -UI.CollapsiblePanel.prototype.remove = function () { - for (var i = 0; i < arguments.length; i++) { - this.content.removeChild(arguments[ i ].dom) - } - - return this -} - -UI.CollapsiblePanel.prototype.clear = function () { - while (this.content.children.length) { - this.content.removeChild(this.content.lastChild) - } -} - -UI.CollapsiblePanel.prototype.toggle = function () { - this.setCollapsed(!this.isCollapsed) -} - -UI.CollapsiblePanel.prototype.collapse = function () { - this.setCollapsed(true) -} - -UI.CollapsiblePanel.prototype.expand = function () { - this.setCollapsed(false) -} - -UI.CollapsiblePanel.prototype.setCollapsed = function (setCollapsed) { - if (setCollapsed) { - this.dom.classList.add('collapsed') - } else { - this.dom.classList.remove('collapsed') - } - - this.isCollapsed = setCollapsed -} - -// Text - -UI.Text = function (text) { - UI.Element.call(this) - - var dom = document.createElement('span') - dom.className = 'Text' - dom.style.display = 'inline-block' - dom.style.verticalAlign = 'middle' - - this.dom = dom - this.setValue(text) - - return this -} - -UI.Text.prototype = Object.create(UI.Element.prototype) - -UI.Text.prototype.setValue = function (value) { - if (value !== undefined) { - this.dom.textContent = value - } - - return this -} - -UI.Text.prototype.setName = function (value) { - this.dom.name = value - - return this -} -// Input - -UI.Input = function (value) { - UI.Element.call(this) - - var scope = this - - var dom = document.createElement('input') - dom.className = 'Input' - dom.style.padding = '2px' - dom.style.border = '1px solid #ccc' - - dom.addEventListener('keydown', function (event) { - event.stopPropagation() - }, false) - - this.dom = dom - this.setValue(value || '') - - return this -} - -UI.Input.prototype = Object.create(UI.Element.prototype) - -UI.Input.prototype.getValue = function () { - return this.dom.value -} - -UI.Input.prototype.setValue = function (value) { - this.dom.value = value - - return this -} - -UI.Input.prototype.setName = function (value) { - this.dom.name = value - - return this -} - -// TextArea - -UI.TextArea = function () { - UI.Element.call(this) - - var scope = this - - var dom = document.createElement('textarea') - dom.className = 'TextArea' - dom.style.padding = '2px' - dom.style.border = '1px solid #ccc' - - dom.addEventListener('keydown', function (event) { - event.stopPropagation() - }, false) - - this.dom = dom - - return this -} - -UI.TextArea.prototype = Object.create(UI.Element.prototype) - -UI.TextArea.prototype.getValue = function () { - return this.dom.value -} - -UI.TextArea.prototype.setValue = function (value) { - this.dom.value = value - - return this -} - -// Select - -UI.Select = function () { - UI.Element.call(this) - - var scope = this - - var dom = document.createElement('select') - dom.className = 'Select' - dom.style.width = '64px' - dom.style.height = '16px' - dom.style.border = '0px' - dom.style.padding = '0px' - - this.dom = dom - - return this -} - -UI.Select.prototype = Object.create(UI.Element.prototype) - -UI.Select.prototype.setMultiple = function (boolean) { - this.dom.multiple = boolean - - return this -} - -UI.Select.prototype.setOptions = function (options) { - var selected = this.dom.value - - while (this.dom.children.length > 0) { - this.dom.removeChild(this.dom.firstChild) - } - - for (var key in options) { - var option = document.createElement('option') - option.value = key - option.innerHTML = options[ key ] - this.dom.appendChild(option) - } - - this.dom.value = selected - - return this -} - -UI.Select.prototype.getValue = function () { - return this.dom.value -} - -UI.Select.prototype.setValue = function (value) { - this.dom.value = value - - return this -} - -UI.Select.prototype.setName = function (value) { - this.dom.name = value - - return this -} - -// FancySelect - -UI.FancySelect = function () { - UI.Element.call(this) - - var scope = this - - var dom = document.createElement('div') - dom.className = 'FancySelect' - dom.tabIndex = 0 // keyup event is ignored without setting tabIndex - - // Broadcast for object selection after arrow navigation - var changeEvent = document.createEvent('HTMLEvents') - changeEvent.initEvent('change', true, true) - - // Prevent native scroll behavior - dom.addEventListener('keydown', function (event) { - switch (event.keyCode) { - case 38: // up - case 40: // down - event.preventDefault() - event.stopPropagation() - break - } - }, false) - - // Keybindings to support arrow navigation - dom.addEventListener('keyup', function (event) { - switch (event.keyCode) { - case 38: // up - case 40: // down - scope.selectedIndex += (event.keyCode == 38) ? -1 : 1 - - if (scope.selectedIndex >= 0 && scope.selectedIndex < scope.options.length) { - // Highlight selected dom elem and scroll parent if needed - scope.setValue(scope.options[ scope.selectedIndex ].value) - - scope.dom.dispatchEvent(changeEvent) - } - - break - } - }, false) - - this.dom = dom - - this.options = [] - this.selectedIndex = -1 - this.selectedValue = null - - return this -} - -UI.FancySelect.prototype = Object.create(UI.Element.prototype) - -UI.FancySelect.prototype.setOptions = function (options) { - var scope = this - - var changeEvent = document.createEvent('HTMLEvents') - changeEvent.initEvent('change', true, true) - - while (scope.dom.children.length > 0) { - scope.dom.removeChild(scope.dom.firstChild) - } - - scope.options = [] - - for (var i = 0; i < options.length; i++) { - var option = options[ i ] - - var div = document.createElement('div') - div.className = 'option' - div.innerHTML = option.html - div.value = option.value - scope.dom.appendChild(div) - - scope.options.push(div) - - div.addEventListener('click', function (event) { - scope.setValue(this.value) - scope.dom.dispatchEvent(changeEvent) - }, false) - } - - return scope -} - -UI.FancySelect.prototype.getValue = function () { - return this.selectedValue -} - -UI.FancySelect.prototype.setValue = function (value) { - for (var i = 0; i < this.options.length; i++) { - var element = this.options[ i ] - - if (element.value === value) { - element.classList.add('active') - - // scroll into view - - var y = element.offsetTop - this.dom.offsetTop - var bottomY = y + element.offsetHeight - var minScroll = bottomY - this.dom.offsetHeight - - if (this.dom.scrollTop > y) { - this.dom.scrollTop = y - } else if (this.dom.scrollTop < minScroll) { - this.dom.scrollTop = minScroll - } - - this.selectedIndex = i - } else { - element.classList.remove('active') - } - } - - this.selectedValue = value - - return this -} - -// Checkbox - -UI.Checkbox = function (boolean) { - UI.Element.call(this) - - var scope = this - - var dom = document.createElement('input') - dom.className = 'Checkbox' - dom.type = 'checkbox' - - this.dom = dom - this.setValue(boolean) - - return this -} - -UI.Checkbox.prototype = Object.create(UI.Element.prototype) - -UI.Checkbox.prototype.getValue = function () { - return this.dom.checked -} - -UI.Checkbox.prototype.setValue = function (value) { - if (value !== undefined) { - this.dom.checked = value - } - - return this -} - -UI.Checkbox.prototype.setName = function (value) { - this.dom.name = value - - return this -} -// Color - -UI.Color = function () { - UI.Element.call(this) - - var scope = this - - var dom = document.createElement('input') - dom.className = 'Color' - dom.style.width = '64px' - dom.style.height = '16px' - dom.style.border = '0px' - dom.style.padding = '0px' - dom.style.backgroundColor = 'transparent' - - try { - dom.type = 'color' - dom.value = '#ffffff' - } catch (exception) {} - - this.dom = dom - - return this -} - -UI.Color.prototype = Object.create(UI.Element.prototype) - -UI.Color.prototype.getValue = function () { - return this.dom.value -} - -UI.Color.prototype.getHexValue = function () { - return parseInt(this.dom.value.substr(1), 16) -} - -UI.Color.prototype.setValue = function (value) { - this.dom.value = value - - return this -} - -UI.Color.prototype.setHexValue = function (hex) { - this.dom.value = '#' + ('000000' + hex.toString(16)).slice(-6) - - return this -} - -// Number - -UI.Number = function (number) { - UI.Element.call(this) - - var scope = this - - var dom = document.createElement('input') - dom.className = 'Number' - dom.value = '0.00' - - dom.addEventListener('keydown', function (event) { - event.stopPropagation() - - if (event.keyCode === 13) dom.blur() - }, false) - - this.min = -Infinity - this.max = Infinity - - this.precision = 2 - this.step = 1 - - this.dom = dom - this.setValue(number) - - var changeEvent = document.createEvent('HTMLEvents') - changeEvent.initEvent('change', true, true) - - var distance = 0 - var onMouseDownValue = 0 - - var pointer = [ 0, 0 ] - var prevPointer = [ 0, 0 ] - - var onMouseDown = function (event) { - event.preventDefault() - - distance = 0 - - onMouseDownValue = parseFloat(dom.value) - - prevPointer = [ event.clientX, event.clientY ] - - document.addEventListener('mousemove', onMouseMove, false) - document.addEventListener('mouseup', onMouseUp, false) - } - - var onMouseMove = function (event) { - var currentValue = dom.value - - pointer = [ event.clientX, event.clientY ] - - distance += (pointer[ 0 ] - prevPointer[ 0 ]) - (pointer[ 1 ] - prevPointer[ 1 ]) - - var modifier = 50 - if (event.shiftKey) modifier = 5 - if (event.ctrlKey) modifier = 500 - - var number = onMouseDownValue + (distance / modifier) * scope.step - - dom.value = Math.min(scope.max, Math.max(scope.min, number)).toFixed(scope.precision) - - if (currentValue !== dom.value) dom.dispatchEvent(changeEvent) - - prevPointer = [ event.clientX, event.clientY ] - } - - var onMouseUp = function (event) { - document.removeEventListener('mousemove', onMouseMove, false) - document.removeEventListener('mouseup', onMouseUp, false) - - if (Math.abs(distance) < 2) { - dom.focus() - dom.select() - } - } - - var onChange = function (event) { - var number = parseFloat(dom.value) - - dom.value = isNaN(number) === false ? number : 0 - } - - var onFocus = function (event) { - dom.style.backgroundColor = '' - dom.style.borderColor = '#ccc' - dom.style.cursor = '' - } - - var onBlur = function (event) { - dom.style.backgroundColor = 'transparent' - dom.style.borderColor = 'transparent' - dom.style.cursor = 'col-resize' - } - - dom.addEventListener('mousedown', onMouseDown, false) - dom.addEventListener('change', onChange, false) - dom.addEventListener('focus', onFocus, false) - dom.addEventListener('blur', onBlur, false) - - return this -} - -UI.Number.prototype = Object.create(UI.Element.prototype) - -UI.Number.prototype.getValue = function () { - return parseFloat(this.dom.value) -} - -UI.Number.prototype.setValue = function (value) { - if (isNaN(value)) { - this.dom.value = NaN - } else if (value !== undefined) { - this.dom.value = value.toFixed(this.precision) - } - - return this -} - -UI.Number.prototype.setRange = function (min, max) { - this.min = min - this.max = max - - return this -} - -UI.Number.prototype.setPrecision = function (precision) { - this.precision = precision - this.setValue(parseFloat(this.dom.value)) - - return this -} - -UI.Number.prototype.setName = function (value) { - this.dom.name = value - - return this -} -// Integer - -UI.Integer = function (number) { - UI.Element.call(this) - - var scope = this - - var dom = document.createElement('input') - dom.className = 'Number' - dom.value = '0.00' - - dom.addEventListener('keydown', function (event) { - event.stopPropagation() - }, false) - - this.min = -Infinity - this.max = Infinity - - this.step = 1 - - this.dom = dom - this.setValue(number) - - var changeEvent = document.createEvent('HTMLEvents') - changeEvent.initEvent('change', true, true) - - var distance = 0 - var onMouseDownValue = 0 - - var pointer = [ 0, 0 ] - var prevPointer = [ 0, 0 ] - - var onMouseDown = function (event) { - event.preventDefault() - - distance = 0 - - onMouseDownValue = parseFloat(dom.value) - - prevPointer = [ event.clientX, event.clientY ] - - document.addEventListener('mousemove', onMouseMove, false) - document.addEventListener('mouseup', onMouseUp, false) - } - - var onMouseMove = function (event) { - var currentValue = dom.value - - pointer = [ event.clientX, event.clientY ] - - distance += (pointer[ 0 ] - prevPointer[ 0 ]) - (pointer[ 1 ] - prevPointer[ 1 ]) - - var modifier = 50 - if (event.shiftKey) modifier = 5 - if (event.ctrlKey) modifier = 500 - - var number = onMouseDownValue + (distance / modifier) * scope.step - - dom.value = Math.min(scope.max, Math.max(scope.min, number)) | 0 - - if (currentValue !== dom.value) dom.dispatchEvent(changeEvent) - - prevPointer = [ event.clientX, event.clientY ] - } - - var onMouseUp = function (event) { - document.removeEventListener('mousemove', onMouseMove, false) - document.removeEventListener('mouseup', onMouseUp, false) - - if (Math.abs(distance) < 2) { - dom.focus() - dom.select() - } - } - - var onChange = function (event) { - var number = parseInt(dom.value) - - if (isNaN(number) === false) { - dom.value = number - } - } - - var onFocus = function (event) { - dom.style.backgroundColor = '' - dom.style.borderColor = '#ccc' - dom.style.cursor = '' - } - - var onBlur = function (event) { - dom.style.backgroundColor = 'transparent' - dom.style.borderColor = 'transparent' - dom.style.cursor = 'col-resize' - } - - dom.addEventListener('mousedown', onMouseDown, false) - dom.addEventListener('change', onChange, false) - dom.addEventListener('focus', onFocus, false) - dom.addEventListener('blur', onBlur, false) - - return this -} - -UI.Integer.prototype = Object.create(UI.Element.prototype) - -UI.Integer.prototype.getValue = function () { - return parseInt(this.dom.value) -} - -UI.Integer.prototype.setValue = function (value) { - if (value !== undefined) { - this.dom.value = value | 0 - } - - return this -} - -UI.Integer.prototype.setRange = function (min, max) { - this.min = min - this.max = max - - return this -} - -UI.Integer.prototype.setName = function (value) { - this.dom.name = value - - return this -} - -UI.Integer.prototype.setStep = function (step) { - this.step = step - - return this -} -// Break - -UI.Break = function () { - UI.Element.call(this) - - var dom = document.createElement('br') - dom.className = 'Break' - - this.dom = dom - - return this -} - -UI.Break.prototype = Object.create(UI.Element.prototype) - -// HorizontalRule - -UI.HorizontalRule = function () { - UI.Element.call(this) - - var dom = document.createElement('hr') - dom.className = 'HorizontalRule' - - this.dom = dom - - return this -} - -UI.HorizontalRule.prototype = Object.create(UI.Element.prototype) - -// Button - -UI.Button = function (value) { - UI.Element.call(this) - - var scope = this - - var dom = document.createElement('button') - dom.className = 'Button' - - this.dom = dom - this.dom.textContent = value - - return this -} - -UI.Button.prototype = Object.create(UI.Element.prototype) - -UI.Button.prototype.setLabel = function (value) { - this.dom.textContent = value - - return this -} - -// Helper - -UI.MenubarHelper = { - - createMenuContainer: function (name, optionsPanel) { - var container = new UI.Panel() - var title = new UI.Panel() - title.setClass('title') - - title.setTextContent(name) - title.setMargin('0px') - title.setPadding('8px') - - container.setClass('menu') - container.add(title) - container.add(optionsPanel) - - return container - }, - - createOption: function (name, callbackHandler, icon) { - var option = new UI.Panel() - option.setClass('option') - - if (icon) { - option.add(new UI.Icon(icon).setWidth('20px')) - option.add(new UI.Text(name)) - } else { - option.setTextContent(name) - } - - option.onClick(callbackHandler) - - return option - }, - - createOptionsPanel: function (menuConfig) { - var options = new UI.Panel() - options.setClass('options') - - menuConfig.forEach(function (option) { - options.add(option) - }) - - return options - }, - - createInput: function (name, callbackHandler) { - var panel = new UI.Panel() - .setClass('option') - - var text = new UI.Text() - .setWidth('70px') - .setValue(name) - - var input = new UI.Input() - .setWidth('40px') - .onKeyDown(callbackHandler) - - panel.add(text) - panel.add(input) - - return panel - }, - - createCheckbox: function (name, value, callbackHandler) { - var panel = new UI.Panel() - .setClass('option') - - var text = new UI.Text() - .setWidth('70px') - .setValue(name) - - var checkbox = new UI.Checkbox() - .setValue(value) - .onClick(callbackHandler) - - panel.add(checkbox) - panel.add(text) - - return panel - }, - - createDivider: function () { - return new UI.HorizontalRule() - } - -} diff --git a/examples/examples/js/ui/ui.ngl.js b/examples/examples/js/ui/ui.ngl.js deleted file mode 100644 index 59815338b..000000000 --- a/examples/examples/js/ui/ui.ngl.js +++ /dev/null @@ -1,368 +0,0 @@ -/** - * @file UI NGL - * @author Alexander Rose - */ - -// Color - -UI.ColorPopupMenu = function () { - var scope = this - - UI.Panel.call(this) - - this.iconText = new UI.Text('') - .setCursor('pointer') - .setClass('fa-stack-1x') - .setFontFamily('Arial, sans-serif') - .setColor('#111') - - this.iconSquare = new UI.Icon('square', 'stack-1x') - // .setMarginTop( "0.05em" ); - - this.menu = new UI.PopupMenu('stack', 'Color') - - this.menu.icon - .setTitle('color') - .setWidth('1em').setHeight('1em').setLineHeight('1em') - .add(this.iconSquare) - .add(this.iconText) - - var changeEvent = document.createEvent('Event') - changeEvent.initEvent('change', true, true) - - this.colorInput = new UI.Input() - .onChange(function () { - scope.setColor(scope.colorInput.getValue()) - scope.dom.dispatchEvent(changeEvent) - }) - - this.colorPicker = new UI.ColorPicker() - .setDisplay('inline-block') - .onChange(function (e) { - scope.setColor(scope.colorPicker.getValue()) - scope.dom.dispatchEvent(changeEvent) - }) - - this.menu - .addEntry('Input', this.colorInput) - .addEntry('Picker', this.colorPicker) - - this.add(this.menu) - - this.setClass('') - .setDisplay('inline') - - return this -} - -UI.ColorPopupMenu.prototype = Object.create(UI.Panel.prototype) - -UI.ColorPopupMenu.prototype.setColor = (function () { - var c = new NGL.Color() - - return function (value) { - c.set(value) - value = '#' + c.getHexString() - - this.colorInput - .setBackgroundColor(value) - .setValue(value) - - this.colorPicker.setValue(value) - - this.iconSquare.setColor(value) - - // perceived brightness (http://alienryderflex.com/hsp.html) - var brightness = Math.sqrt( - c.r * 255 * c.r * 255 * 0.241 + - c.g * 255 * c.g * 255 * 0.691 + - c.b * 255 * c.b * 255 * 0.068 - ) - - if (brightness > 130) { - this.iconText.setColor('#000000') - this.colorInput.setColor('#000000') - } else { - this.iconText.setColor('#FFFFFF') - this.colorInput.setColor('#FFFFFF') - } - - return this - } -}()) - -UI.ColorPopupMenu.prototype.getColor = function () { - return this.colorInput.getValue() -} - -UI.ColorPopupMenu.prototype.getValue = function () { - return this.getColor() -} - -UI.ColorPopupMenu.prototype.setValue = function (value) { - this.setColor(value) - - return this -} - -UI.ColorPopupMenu.prototype.dispose = function () { - this.menu.dispose() - - UI.Panel.prototype.dispose.call(this) -} - -// Vector3 - -UI.Vector3 = function (value) { - UI.Panel.call(this).setDisplay('inline-block') - - this.xNumber = new UI.Number(0).setWidth('40px') - this.yNumber = new UI.Number(0).setWidth('40px') - this.zNumber = new UI.Number(0).setWidth('40px') - - this.add(this.xNumber, this.yNumber, this.zNumber) - this.setValue(value) - - var changeEvent = document.createEvent('Event') - changeEvent.initEvent('change', true, true) - - this.xNumber.onChange(function () { - this.dom.dispatchEvent(changeEvent) - }.bind(this)) - this.yNumber.onChange(function () { - this.dom.dispatchEvent(changeEvent) - }.bind(this)) - this.zNumber.onChange(function () { - this.dom.dispatchEvent(changeEvent) - }.bind(this)) - - return this -} - -UI.Vector3.prototype = Object.create(UI.Panel.prototype) - -UI.Vector3.prototype.getValue = function () { - return { - x: this.xNumber.getValue(), - y: this.yNumber.getValue(), - z: this.zNumber.getValue() - } -} - -UI.Vector3.prototype.setValue = function (value) { - if (value) { - this.xNumber.setValue(value.x) - this.yNumber.setValue(value.y) - this.zNumber.setValue(value.z) - } - - return this -} - -UI.Vector3.prototype.setPrecision = function (precision) { - this.xNumber.setPrecision(precision) - this.yNumber.setPrecision(precision) - this.zNumber.setPrecision(precision) - - return this -} - -UI.Vector3.prototype.setRange = function (min, max) { - this.xNumber.setRange(min, max) - this.yNumber.setRange(min, max) - this.zNumber.setRange(min, max) - - return this -} - -// Selection - -UI.SelectionInput = function (selection) { - UI.AdaptiveTextArea.call(this) - - this.setSpellcheck(false) - - if (!(selection.type === 'selection')) { - NGL.error('UI.SelectionInput: not a selection', selection) - - return this - } - - this.setValue(selection.string) - - this.selection = selection - - var scope = this - - var signals = selection.signals - - signals.stringChanged.add(function (string) { - scope.setValue(string) - }) - - this.onEnter() - - return this -} - -UI.SelectionInput.prototype = Object.create(UI.AdaptiveTextArea.prototype) - -UI.SelectionInput.prototype.setValue = function (value) { - UI.AdaptiveTextArea.prototype.setValue.call(this, value) - - return this -} - -UI.SelectionInput.prototype.onEnter = function (callback) { - // TODO more a private method - - var scope = this - - var check = function (string) { - var selection = new NGL.Selection(string) - - return !selection.selection[ 'error' ] - } - - this.onKeyPress(function (e) { - var value = scope.getValue() - var character = String.fromCharCode(e.which) - - if (e.keyCode === 13) { - e.preventDefault() - - if (check(value)) { - if (typeof callback === 'function') { - callback(value) - } else { - scope.selection.setString(value) - } - - scope.setBackgroundColor('white') - } else { - scope.setBackgroundColor('tomato') - } - } else if (scope.selection.string !== value + character) { - scope.setBackgroundColor('skyblue') - } else { - scope.setBackgroundColor('white') - } - }) - - this.onKeyUp(function (e) { - var value = scope.getValue() - - if (!check(value)) { - scope.setBackgroundColor('tomato') - } else if (scope.selection.string === scope.getValue()) { - scope.setBackgroundColor('white') - } else { - scope.setBackgroundColor('skyblue') - } - }) - - return this -} - -UI.SelectionPanel = function (selection) { - UI.Panel.call(this) - - this.icon = new UI.Icon('filter') - .setTitle('filter selection') - .addClass('lg') - .setMarginRight('10px') - - this.input = new UI.SelectionInput(selection) - - this.add(this.icon, this.input) - - return this -} - -UI.SelectionPanel.prototype = Object.create(UI.Panel.prototype) - -UI.SelectionPanel.prototype.setInputWidth = function (value) { - this.input.setWidth(value) - - return this -} - -// Component - -UI.ComponentPanel = function (component) { - UI.Panel.call(this) - - var stage = component.stage - var signals = component.signals - - signals.nameChanged.add(function (value) { - name.setValue(value) - }) - - signals.visibilityChanged.add(function (value) { - toggle.setValue(value) - }) - - signals.disposed.add(function () { - menu.dispose() - }) - - // Name - - var name = new UI.EllipsisText(component.name) - .setWidth('100px') - - // Actions - - var toggle = new UI.ToggleIcon(component.visible, 'eye', 'eye-slash') - .setTitle('hide/show') - .setCursor('pointer') - .setMarginLeft('25px') - .onClick(function () { - component.setVisibility(!component.visible) - }) - - var center = new UI.Icon('bullseye') - .setTitle('center') - .setCursor('pointer') - .setMarginLeft('10px') - .onClick(function () { - component.autoView(1000) - }) - - var dispose = new UI.DisposeIcon() - .setMarginLeft('10px') - .setDisposeFunction(function () { - stage.removeComponent(component) - }) - - // Menu - - var menu = new UI.PopupMenu('bars', component.type) - .setMarginLeft('46px') - .setEntryLabelWidth('110px') - - // - - this.add(name, toggle, center, dispose, menu) - - // - - this.menu = menu - - return this -} - -UI.ComponentPanel.prototype = Object.create(UI.Panel.prototype) - -UI.ComponentPanel.prototype.addMenuEntry = function (label, entry) { - this.menu.addEntry(label, entry) - - return this -} - -UI.ComponentPanel.prototype.setMenuDisplay = function (value) { - this.menu.setMenuDisplay(value) - - return this -} diff --git a/examples/examples/mobile.html b/examples/examples/mobile.html deleted file mode 100644 index 0ee385bcc..000000000 --- a/examples/examples/mobile.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - NGL - mobile - - - - - - - -
-
-
- -
-
- - diff --git a/examples/examples/parallel.html b/examples/examples/parallel.html deleted file mode 100644 index 4996ccc20..000000000 --- a/examples/examples/parallel.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - NGL - parallel - - - - - - - -
- - \ No newline at end of file diff --git a/examples/examples/scripts/color/atomindex.js b/examples/examples/scripts/color/atomindex.js deleted file mode 100644 index a537a14b3..000000000 --- a/examples/examples/scripts/color/atomindex.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://1blu.mmtf').then(function (o) { - o.addRepresentation('ball+stick', { color: 'atomindex' }) - o.autoView() -}) diff --git a/examples/examples/scripts/color/bfactor.js b/examples/examples/scripts/color/bfactor.js deleted file mode 100644 index 7d5e8179e..000000000 --- a/examples/examples/scripts/color/bfactor.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://1blu.mmtf').then(function (o) { - o.addRepresentation('cartoon', { color: 'bfactor' }) - o.autoView() -}) diff --git a/examples/examples/scripts/color/chainid.js b/examples/examples/scripts/color/chainid.js deleted file mode 100644 index 288964446..000000000 --- a/examples/examples/scripts/color/chainid.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://3SN6.cif').then(function (o) { - o.addRepresentation('cartoon', { color: 'chainid' }) - o.autoView() -}) diff --git a/examples/examples/scripts/color/custom.js b/examples/examples/scripts/color/custom.js deleted file mode 100644 index f3dddcf5f..000000000 --- a/examples/examples/scripts/color/custom.js +++ /dev/null @@ -1,17 +0,0 @@ - -var schemeId = NGL.ColormakerRegistry.addScheme(function (params) { - this.atomColor = function (atom) { - if (atom.serial < 1000) { - return 0x0000FF // blue - } else if (atom.serial > 2000) { - return 0xFF0000 // red - } else { - return 0x00FF00 // green - } - } -}) - -stage.loadFile('data://3dqb.pdb').then(function (o) { - o.addRepresentation('cartoon', { color: schemeId }) - o.autoView() -}) diff --git a/examples/examples/scripts/color/electrostatic.js b/examples/examples/scripts/color/electrostatic.js deleted file mode 100644 index 997abbfef..000000000 --- a/examples/examples/scripts/color/electrostatic.js +++ /dev/null @@ -1,9 +0,0 @@ - -stage.loadFile('data://3dqb.pdb').then(function (o) { - o.addRepresentation('surface', { - sele: 'polymer', - colorScheme: 'electrostatic', - surfaceType: 'av' - }) - o.autoView() -}) diff --git a/examples/examples/scripts/color/element.js b/examples/examples/scripts/color/element.js deleted file mode 100644 index 7cb9c0d34..000000000 --- a/examples/examples/scripts/color/element.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://1blu.mmtf').then(function (o) { - o.addRepresentation('ball+stick', { color: 'element' }) - o.autoView() -}) diff --git a/examples/examples/scripts/color/modelindex.js b/examples/examples/scripts/color/modelindex.js deleted file mode 100644 index 47e5088fc..000000000 --- a/examples/examples/scripts/color/modelindex.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://1LVZ.cif').then(function (o) { - o.addRepresentation('cartoon', { color: 'modelindex' }) - o.autoView() -}) diff --git a/examples/examples/scripts/color/partialcharge.js b/examples/examples/scripts/color/partialcharge.js deleted file mode 100644 index 3913cca3d..000000000 --- a/examples/examples/scripts/color/partialcharge.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://adrenalin.mol2').then(function (o) { - o.addRepresentation('ball+stick', { color: 'partialCharge' }) - o.autoView() -}) diff --git a/examples/examples/scripts/color/resname.js b/examples/examples/scripts/color/resname.js deleted file mode 100644 index 7efd9704a..000000000 --- a/examples/examples/scripts/color/resname.js +++ /dev/null @@ -1,7 +0,0 @@ - -stage.loadFile('data://1d66.pdb').then(function (o) { - o.addRepresentation('cartoon', { color: 'resname' }) - o.addRepresentation('base', { color: 'resname' }) - o.addRepresentation('ball+stick', { color: 'resname', visible: false }) - o.autoView() -}) diff --git a/examples/examples/scripts/color/selection.js b/examples/examples/scripts/color/selection.js deleted file mode 100644 index 6892b57be..000000000 --- a/examples/examples/scripts/color/selection.js +++ /dev/null @@ -1,25 +0,0 @@ - -var schemeId = NGL.ColormakerRegistry.addSelectionScheme([ - [ - 'atomindex', - '64-74 or 134-154 or 222-254 or 310-310 or 322-326', - { scale: ['firebrick', 'red', 'orangered'] } - ], - [ 'green', '311-322' ], - [ - 'atomindex', - '40-63 or 75-95 or 112-133 or 155-173 or 202-221 or 255-277 or 289-309', - { scale: ['gold', 'yellow', 'lightyellow'] } - ], - [ - 'atomindex', - '1-39 or 96-112 or 174-201 or 278-288', - { scale: ['blue', 'dodgerblue', 'cyan'] } - ], - [ 'white', '*' ] -], 'TMDET 3dqb') - -stage.loadFile('data://3dqb.pdb').then(function (o) { - o.addRepresentation('cartoon', { color: schemeId }) - o.autoView() -}) diff --git a/examples/examples/scripts/color/sstruc.js b/examples/examples/scripts/color/sstruc.js deleted file mode 100644 index 0327ce9dc..000000000 --- a/examples/examples/scripts/color/sstruc.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://1blu.mmtf').then(function (o) { - o.addRepresentation('cartoon', { color: 'sstruc' }) - o.autoView() -}) diff --git a/examples/examples/scripts/color/volume-esp.js b/examples/examples/scripts/color/volume-esp.js deleted file mode 100644 index 263a8ddc4..000000000 --- a/examples/examples/scripts/color/volume-esp.js +++ /dev/null @@ -1,25 +0,0 @@ - -Promise.all([ - stage.loadFile('data://hf.dx'), - stage.loadFile('data://esp.dx'), - stage.loadFile('data://esp.mol', { ext: 'sdf' }) -]).then(function (l) { - var hfComponent = l[ 0 ] - var espComponent = l[ 1 ] - var molComponent = l[ 2 ] - - molComponent.addRepresentation('licorice', { multipleBond: true }) - - hfComponent.addRepresentation('surface', - { isolevel: 0.002, - isolevelType: 'value', - opacity: 0.95, - side: 'front', - colorScheme: 'volume', - colorVolume: espComponent.volume, - colorScale: [ 0xff0000, 0xffff00, 0x00ff00, 0x00ffff, 0x0000ff ], - colorMode: 'rgb', - colorDomain: [ -0.05, 0.05 ] - }) - stage.autoView() -}) diff --git a/examples/examples/scripts/color/volume.js b/examples/examples/scripts/color/volume.js deleted file mode 100644 index 3960a0888..000000000 --- a/examples/examples/scripts/color/volume.js +++ /dev/null @@ -1,27 +0,0 @@ - -Promise.all([ - stage.loadFile('data://betaGal.mrc'), - stage.loadFile('data://localResolution.mrc', { voxelSize: 3.54 }) -]).then(function (l) { - var betaGal = l[ 0 ] - var localResolution = l[ 1 ] - betaGal.addRepresentation('surface', { - colorVolume: localResolution.volume, - colorScheme: 'volume', - colorScale: 'rwb', - colorReverse: true, - colorDomain: [ 5, 14 ] - }) - localResolution.addRepresentation('dot', { - thresholdMin: 0, - thresholdMax: 8, - thresholdType: 'value', - dotType: 'sphere', - radius: 0.6, - colorScheme: 'value', - colorScale: 'rwb', - colorReverse: true, - colorDomain: [ 5, 14 ] - }) - stage.autoView() -}) diff --git a/examples/examples/scripts/component/getByName.js b/examples/examples/scripts/component/getByName.js deleted file mode 100644 index febe0cfbb..000000000 --- a/examples/examples/scripts/component/getByName.js +++ /dev/null @@ -1,12 +0,0 @@ - -// name a loaded component and access it via `stage.getComponentsByName` - -stage.loadFile('data://1crn.pdb', { name: 'myProtein' }).then(function (o) { - o.autoView() - o.addRepresentation('cartoon') -}).then(function () { - stage.getComponentsByName('myProtein').addRepresentation('distance', { - atomPair: [ [ '10.CA', '25.CA' ] ], - color: 'skyblue' - }) -}) diff --git a/examples/examples/scripts/component/matrix.js b/examples/examples/scripts/component/matrix.js deleted file mode 100644 index 7bc8d2ec2..000000000 --- a/examples/examples/scripts/component/matrix.js +++ /dev/null @@ -1,15 +0,0 @@ - -// Load a protein -stage.loadFile('data://1crn.pdb').then(function (o) { - o.addRepresentation('cartoon') - stage.autoView() -}) - -// Load the same protein and move it -stage.loadFile('data://1crn.pdb').then(function (o) { - o.setPosition([ 20, 0, 0 ]) - o.setRotation([ 2, 0, 0 ]) - o.setScale(0.5) - o.addRepresentation('cartoon', { color: 'orange' }) - stage.autoView() -}) diff --git a/examples/examples/scripts/component/shape-buffer.js b/examples/examples/scripts/component/shape-buffer.js deleted file mode 100644 index e5f3933cb..000000000 --- a/examples/examples/scripts/component/shape-buffer.js +++ /dev/null @@ -1,19 +0,0 @@ - -var shape = new NGL.Shape('shape') -var sphereBuffer = new NGL.SphereBuffer({ - position: new Float32Array([ 0, 0, 0, 4, 0, 0 ]), - color: new Float32Array([ 1, 0, 0, 1, 1, 0 ]), - radius: new Float32Array([ 1, 1.2 ]) -}) -shape.addBuffer(sphereBuffer) -var boxBuffer = new NGL.BoxBuffer({ - position: new Float32Array([ 0, 3, 0, -2, 0, 0 ]), - color: new Float32Array([ 1, 0, 1, 0, 1, 0 ]), - size: new Float32Array([ 2, 1.5 ]), - heightAxis: new Float32Array([ 0, 1, 1, 0, 2, 0 ]), - depthAxis: new Float32Array([ 1, 0, 1, 0, 0, 2 ]) -}) -shape.addBuffer(boxBuffer) -var shapeComp = stage.addComponentFromObject(shape) -shapeComp.addRepresentation('buffer') -shapeComp.autoView() diff --git a/examples/examples/scripts/component/shape-cat.js b/examples/examples/scripts/component/shape-cat.js deleted file mode 100644 index 8def66081..000000000 --- a/examples/examples/scripts/component/shape-cat.js +++ /dev/null @@ -1,32 +0,0 @@ - -var grey = [ 0.8, 0.8, 0.8 ] -var darkgrey = [ 0.6, 0.6, 0.6 ] - -var shape = new NGL.Shape('shape', { - labelParams: { attachment: 'middle-center' }, - sphereDetail: 4, - radialSegments: 100 -}) -shape.addEllipsoid([ 0, 0, 0 ], grey, 4, [ 0, 3, 0 ], [ 0, 0, 1 ], 'Face') -shape.addSphere([ -2, 1, -1 ], darkgrey, 0.3, 'Right eye') -shape.addSphere([ 2, 1, -1 ], darkgrey, 0.3, 'Left eye') -shape.addSphere([ 0, 0, -1 ], darkgrey, 0.5, 'Nose') -shape.addEllipsoid([ -1, -1, -1 ], darkgrey, 1.3, [ 0, 1, 0 ], [ 0, 0, 0.3 ], 'Right cheek') -shape.addEllipsoid([ 1, -1, -1 ], darkgrey, 1.3, [ 0, 1, 0 ], [ 0, 0, 0.3 ], 'Left cheek') -shape.addCone([ 2.5, 1.7, 0 ], [ 4, 3, 0 ], darkgrey, 0.8, 'Left ear') -shape.addCone([ -2.5, 1.7, 0 ], [ -4, 3, 0 ], darkgrey, 0.8, 'Right ear') -shape.addCylinder([ -1, -1, -1 ], [ -4.3, -0.2, -1.2 ], darkgrey, 0.1, 'Whisker') -shape.addCylinder([ -1, -1, -1 ], [ -4.5, -1.2, -1.2 ], darkgrey, 0.1, 'Whisker') -shape.addCylinder([ -1, -1, -1 ], [ -4.2, -2.2, -1.2 ], darkgrey, 0.1, 'Whisker') -shape.addCylinder([ 1, -1, -1 ], [ 4.3, -0.2, -1.2 ], darkgrey, 0.1, 'Whisker') -shape.addCylinder([ 1, -1, -1 ], [ 4.5, -1.2, -1.2 ], darkgrey, 0.1, 'Whisker') -shape.addCylinder([ 1, -1, -1 ], [ 4.2, -2.2, -1.2 ], darkgrey, 0.1, 'Whisker') -shape.addText([ 0, 4, -1 ], [ 0.2, 0.5, 0.8 ], 2.5, 'Meow') - -var shapeComp = stage.addComponentFromObject(shape) -shapeComp.addRepresentation('buffer') -shapeComp.autoView() - -setTimeout(function () { - stage.setRock([ 0, 1, 0 ], 0.005, 0.3) -}, 1000) diff --git a/examples/examples/scripts/component/shape-wireframe.js b/examples/examples/scripts/component/shape-wireframe.js deleted file mode 100644 index cd592077c..000000000 --- a/examples/examples/scripts/component/shape-wireframe.js +++ /dev/null @@ -1,8 +0,0 @@ - -var shape = new NGL.Shape('shape', { disableImpostor: true, radialSegments: 10 }) -shape.addSphere([ -3.5, 2, 2 ], [ 1, 0.5, 0 ], 3) -shape.addArrow([ 2, 2, 7 ], [ 10, -3, -3 ], [ 1, 0.5, 1 ], 1.0) -shape.addText([ 0, -2, 0 ], [ 0.2, 0.5, 0.8 ], 2.5, 'wire-sphere') -var shapeComp = stage.addComponentFromObject(shape) -shapeComp.addRepresentation('buffer', { wireframe: true }) -stage.autoView() diff --git a/examples/examples/scripts/component/shape.js b/examples/examples/scripts/component/shape.js deleted file mode 100644 index c5c70245f..000000000 --- a/examples/examples/scripts/component/shape.js +++ /dev/null @@ -1,23 +0,0 @@ - -var shape = new NGL.Shape('shape', { dashedCylinder: true }) -shape.addMesh( - [ 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1 ], - [ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 ], - undefined, undefined, 'My mesh' -) -shape.addSphere([ 0, 0, 9 ], [ 1, 0, 0 ], 1.5) -shape.addSphere([ 12, 5, 15 ], [ 1, 0.5, 0 ], 1) -shape.addEllipsoid([ 6, 0, 0 ], [ 1, 0, 0 ], 1.5, [ 3, 0, 0 ], [ 0, 2, 0 ]) -shape.addCylinder([ 0, 2, 7 ], [ 0, 0, 9 ], [ 1, 1, 0 ], 0.5, 'My Cylinder') -shape.addCone([ 0, 2, 7 ], [ 0, 3, 3 ], [ 1, 1, 0 ], 1.5) -shape.addArrow([ 1, 2, 7 ], [ 30, 3, 3 ], [ 1, 0, 1 ], 1.0) -shape.addArrow([ 2, 2, 7 ], [ 30, -3, -3 ], [ 1, 0.5, 1 ], 1.0) -shape.addBox([ 23, 1, 2 ], [ 0, 1, 0 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]) -shape.addTetrahedron([ 27, 0, 1 ], [ 0, 1, 0 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]) -shape.addOctahedron([ 8, 5, 14 ], [ 0, 1, 0 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]) -shape.addTorus([ 16, 5, 14 ], [ 0, 1, 0 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]) -shape.addText([ 15, -4, 4 ], [ 0.2, 0.5, 0.8 ], 2.5, 'Hello') - -var shapeComp = stage.addComponentFromObject(shape) -shapeComp.addRepresentation('buffer') -shapeComp.autoView() diff --git a/examples/examples/scripts/component/structure-autoChainName.js b/examples/examples/scripts/component/structure-autoChainName.js deleted file mode 100644 index 76b0dc9ad..000000000 --- a/examples/examples/scripts/component/structure-autoChainName.js +++ /dev/null @@ -1,8 +0,0 @@ - -stage.loadFile('data://Bace1Trimer-inDPPC.gro', { - sele: ':A or :B or DPPC' -}).then(function (o) { - o.addRepresentation('cartoon') - o.addRepresentation('licorice', { sele: 'DPPC' }) - o.autoView() -}) diff --git a/examples/examples/scripts/component/structure-biomol.js b/examples/examples/scripts/component/structure-biomol.js deleted file mode 100644 index 37950cdf3..000000000 --- a/examples/examples/scripts/component/structure-biomol.js +++ /dev/null @@ -1,12 +0,0 @@ - -console.time('load-to-render') -stage.loadFile('data://4opj.cif').then(function (o) { - o.addRepresentation('cartoon', { assembly: 'BU1', opacity: 0.5, side: 'back' }) - o.addRepresentation('ribbon', { assembly: 'SUPERCELL', color: 'grey', scale: 1.0, visible: false }) - o.addRepresentation('backbone', { assembly: 'AU' }) - o.addRepresentation('surface', { assembly: 'BU2' }) - stage.autoView() - stage.tasks.onZeroOnce(function () { - console.timeEnd('load-to-render') - }) -}) diff --git a/examples/examples/scripts/component/structure-biomolSimple.js b/examples/examples/scripts/component/structure-biomolSimple.js deleted file mode 100644 index f8a0b0fb6..000000000 --- a/examples/examples/scripts/component/structure-biomolSimple.js +++ /dev/null @@ -1,11 +0,0 @@ - -stage.loadFile('data://1U19.cif').then(function (o) { - o.addRepresentation('licorice') - o.addRepresentation('cartoon', { - assembly: 'BU1', color: 0xFF1111 - }) - o.addRepresentation('cartoon', { - assembly: 'BU2', color: 0x11FF11 - }) - o.autoView() -}) diff --git a/examples/examples/scripts/component/structure-bondOrders.js b/examples/examples/scripts/component/structure-bondOrders.js deleted file mode 100644 index aaa74cf81..000000000 --- a/examples/examples/scripts/component/structure-bondOrders.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://4umt_47w.sdf').then(function (o) { - o.addRepresentation('licorice', { multipleBond: 'symmetric' }) - stage.autoView() -}) diff --git a/examples/examples/scripts/component/structure-coarseGrained.js b/examples/examples/scripts/component/structure-coarseGrained.js deleted file mode 100644 index 2059fbea5..000000000 --- a/examples/examples/scripts/component/structure-coarseGrained.js +++ /dev/null @@ -1,7 +0,0 @@ - -stage.loadFile('data://BaceCg.pdb').then(function (o) { - o.addRepresentation('cartoon') - o.addRepresentation('rope', { sele: 'helix' }) - o.addRepresentation('ball+stick') - o.autoView() -}) diff --git a/examples/examples/scripts/component/structure-cyclic.js b/examples/examples/scripts/component/structure-cyclic.js deleted file mode 100644 index bda4ef4b2..000000000 --- a/examples/examples/scripts/component/structure-cyclic.js +++ /dev/null @@ -1,7 +0,0 @@ - -stage.loadFile('data://1sfi.cif').then(function (o) { - o.addRepresentation('cartoon', { color: 'chainindex' }) - o.addRepresentation('backbone') - o.addRepresentation('trace', { linewidth: 3 }) - o.autoView() -}) diff --git a/examples/examples/scripts/component/structure-dna.js b/examples/examples/scripts/component/structure-dna.js deleted file mode 100644 index 6d404c844..000000000 --- a/examples/examples/scripts/component/structure-dna.js +++ /dev/null @@ -1,14 +0,0 @@ - -stage.loadFile('data://1d66.pdb').then(function (o) { - o.addRepresentation('cartoon', { - sele: 'nucleic', wireframe: false - }) - o.addRepresentation('base', { - sele: '*', color: 'resname' - }) - o.addRepresentation('licorice', { - sele: 'nucleic', color: 'element', visible: false - }) - - o.autoView('nucleic') -}) diff --git a/examples/examples/scripts/component/structure-multiModel.js b/examples/examples/scripts/component/structure-multiModel.js deleted file mode 100644 index cc4386ab3..000000000 --- a/examples/examples/scripts/component/structure-multiModel.js +++ /dev/null @@ -1,15 +0,0 @@ - -stage.loadFile('data://1LVZ.pdb', { - firstModelOnly: true -}).then(function (o) { - o.addRepresentation('cartoon', { sele: '*' }) - stage.autoView() -}) - -stage.loadFile('data://md_1u19_trj.gro', { - asTrajectory: true -}).then(function (o) { - o.addRepresentation('cartoon', { sele: '*' }) - o.addTrajectory() - stage.autoView() -}) diff --git a/examples/examples/scripts/component/structure-superpose.js b/examples/examples/scripts/component/structure-superpose.js deleted file mode 100644 index 07dbffd9b..000000000 --- a/examples/examples/scripts/component/structure-superpose.js +++ /dev/null @@ -1,25 +0,0 @@ - -var s = '1-320:A' - -Promise.all([ - - stage.loadFile('data://1u19.pdb', { - sele: ':A' - }).then(function (o) { - o.addRepresentation('cartoon', { sele: s }) - o.addRepresentation('ball+stick', { sele: s }) - return o - }), - - stage.loadFile('data://3dqb.pdb', { - sele: ':A' - }).then(function (o) { - o.addRepresentation('cartoon', { sele: s }) - o.addRepresentation('licorice', { sele: s }) - return o - }) - -]).then(function (ol) { - ol[ 0 ].superpose(ol[ 1 ], false, s) - ol[ 0 ].autoView(':A') -}) diff --git a/examples/examples/scripts/component/transform.js b/examples/examples/scripts/component/transform.js deleted file mode 100644 index 60d8e6fd5..000000000 --- a/examples/examples/scripts/component/transform.js +++ /dev/null @@ -1,21 +0,0 @@ - -Promise.all([ - - stage.loadFile('data://d1h4vb1.ent'), - stage.loadFile('data://d1nj1a1.ent') - -]).then(function (ol) { - ol[ 0 ].addRepresentation('cartoon', { color: 'skyblue' }) - ol[ 1 ].addRepresentation('cartoon', { color: 'tomato' }) - - var m = new NGL.Matrix4().fromArray([ - -0.4736676916, -0.0672340378, -0.8781335332, -47.8160381451, - -0.875018823, -0.077179501, 0.4778968341, -17.6453935901, - -0.0999048417, 0.9947476609, -0.0222736126, 78.0472326663, - 0, 0, 0, 1 - ]).transpose() - - ol[ 1 ].setTransform(m) - - stage.autoView() -}) diff --git a/examples/examples/scripts/interactive/annotation.js b/examples/examples/scripts/interactive/annotation.js deleted file mode 100644 index 8b943c62d..000000000 --- a/examples/examples/scripts/interactive/annotation.js +++ /dev/null @@ -1,31 +0,0 @@ - -stage.loadFile('data://3SN6.cif').then(function (o) { - o.addRepresentation('cartoon', { color: 'chainname' }) - - var chainData = { - 'A': { text: 'alpha subunit', color: 'firebrick' }, - 'B': { text: 'beta subunit', color: 'orange' }, - 'G': { text: 'gamma subunit', color: 'khaki' }, - 'R': { text: 'beta 2 adrenergic receptor', color: 'skyblue' }, - 'N': { text: 'nanobody', color: 'royalblue' } - } - - var ap = o.structure.getAtomProxy() - o.structure.eachChain(function (cp) { - ap.index = cp.atomOffset + Math.floor(cp.atomCount / 2) - var elm = document.createElement('div') - elm.innerText = chainData[ cp.chainname ].text - elm.style.color = 'black' - elm.style.backgroundColor = chainData[ cp.chainname ].color - elm.style.padding = '8px' - o.addAnnotation(ap.positionToVector3(), elm) - }, new NGL.Selection('polymer')) - - o.autoView() - - var pa = o.structure.getPrincipalAxes() - var q = pa.getRotationQuaternion() - q.multiply(o.quaternion.clone().inverse()) - stage.animationControls.rotate(q, 0) - stage.animationControls.move(o.getCenter(), 0) -}) diff --git a/examples/examples/scripts/interactive/crosslinking.js b/examples/examples/scripts/interactive/crosslinking.js deleted file mode 100644 index 344ff5482..000000000 --- a/examples/examples/scripts/interactive/crosslinking.js +++ /dev/null @@ -1,884 +0,0 @@ -// Handle window resizing -window.addEventListener('resize', function () { - stage.handleResize() -}, false) - -var newDiv = document.getElementById('viewport').appendChild(document.createElement('div')) -newDiv.setAttribute('style', 'position: absolute; top: 0; left: 20px') -newDiv.innerHTML = '

Example Cross-Links over Human Serum Albumin

Data courtessy of Adam Belsom, Rappsilber Lab

Cross-Link Quality Filter

' - -// example crosslink data -var links = [{ - 'atoms': [3296, 3924], - 'data': { - 'score': 19 - } -}, { - 'atoms': [1497, 3368], - 'data': { - 'score': 17.34 - } -}, { - 'atoms': [955, 1278], - 'data': { - 'score': 17.32 - } -}, { - 'atoms': [1004, 1290], - 'data': { - 'score': 17.03 - } -}, { - 'atoms': [1029, 1290], - 'data': { - 'score': 16.94 - } -}, { - 'atoms': [2077, 2257], - 'data': { - 'score': 16.5 - } -}, { - 'atoms': [1641, 2767], - 'data': { - 'score': 15.92 - } -}, { - 'atoms': [3287, 3924], - 'data': { - 'score': 15.83 - } -}, { - 'atoms': [2687, 2850], - 'data': { - 'score': 15.73 - } -}, { - 'atoms': [949, 1290], - 'data': { - 'score': 15.7 - } -}, { - 'atoms': [1040, 1290], - 'data': { - 'score': 15.23 - } -}, { - 'atoms': [949, 1278], - 'data': { - 'score': 15.16 - } -}, { - 'atoms': [306, 541], - 'data': { - 'score': 14.69 - } -}, { - 'atoms': [1004, 1278], - 'data': { - 'score': 14.5 - } -}, { - 'atoms': [1013, 1290], - 'data': { - 'score': 14.37 - } -}, { - 'atoms': [3183, 4328], - 'data': { - 'score': 14.19 - } -}, { - 'atoms': [1884, 1900], - 'data': { - 'score': 13.99 - } -}, { - 'atoms': [812, 3684], - 'data': { - 'score': 13.94 - } -}, { - 'atoms': [1013, 1258], - 'data': { - 'score': 13.89 - } -}, { - 'atoms': [3384, 4113], - 'data': { - 'score': 13.78 - } -}, { - 'atoms': [3303, 3924], - 'data': { - 'score': 13.69 - } -}, { - 'atoms': [1497, 3377], - 'data': { - 'score': 13.42 - } -}, { - 'atoms': [329, 541], - 'data': { - 'score': 13.4 - } -}, { - 'atoms': [955, 1309], - 'data': { - 'score': 13.38 - } -}, { - 'atoms': [89, 1278], - 'data': { - 'score': 13.35 - } -}, { - 'atoms': [462, 479], - 'data': { - 'score': 13.17 - } -}, { - 'atoms': [399, 541], - 'data': { - 'score': 13.14 - } -}, { - 'atoms': [1493, 1511], - 'data': { - 'score': 13.11 - } -}, { - 'atoms': [1497, 3361], - 'data': { - 'score': 13.09 - } -}, { - 'atoms': [688, 742], - 'data': { - 'score': 13.08 - } -}, { - 'atoms': [321, 541], - 'data': { - 'score': 13.05 - } -}, { - 'atoms': [2850, 2983], - 'data': { - 'score': 13.02 - } -}, { - 'atoms': [1194, 1565], - 'data': { - 'score': 13 - } -}, { - 'atoms': [996, 1290], - 'data': { - 'score': 12.91 - } -}, { - 'atoms': [1497, 3571], - 'data': { - 'score': 12.76 - } -}, { - 'atoms': [98, 1258], - 'data': { - 'score': 12.74 - } -}, { - 'atoms': [77, 1290], - 'data': { - 'score': 12.72 - } -}, { - 'atoms': [263, 1057], - 'data': { - 'score': 12.69 - } -}, { - 'atoms': [955, 1231], - 'data': { - 'score': 12.68 - } -}, { - 'atoms': [955, 1290], - 'data': { - 'score': 12.66 - } -}, { - 'atoms': [1215, 1278], - 'data': { - 'score': 12.62 - } -}, { - 'atoms': [1668, 1831], - 'data': { - 'score': 12.56 - } -}, { - 'atoms': [69, 1258], - 'data': { - 'score': 12.47 - } -}, { - 'atoms': [3943, 4001], - 'data': { - 'score': 12.46 - } -}, { - 'atoms': [955, 1258], - 'data': { - 'score': 12.39 - } -}, { - 'atoms': [967, 1290], - 'data': { - 'score': 12.33 - } -}, { - 'atoms': [1493, 3346], - 'data': { - 'score': 12.32 - } -}, { - 'atoms': [2065, 2308], - 'data': { - 'score': 12.23 - } -}, { - 'atoms': [1632, 2767], - 'data': { - 'score': 12.2 - } -}, { - 'atoms': [1004, 1258], - 'data': { - 'score': 12.16 - } -}, { - 'atoms': [1565, 2362], - 'data': { - 'score': 12.15 - } -}, { - 'atoms': [77, 1258], - 'data': { - 'score': 12.09 - } -}, { - 'atoms': [1159, 1557], - 'data': { - 'score': 12.04 - } -}, { - 'atoms': [1652, 2767], - 'data': { - 'score': 12.03 - } -}, { - 'atoms': [4412, 4510], - 'data': { - 'score': 11.95 - } -}, { - 'atoms': [1242, 1565], - 'data': { - 'score': 11.95 - } -}, { - 'atoms': [3353, 3421], - 'data': { - 'score': 11.93 - } -}, { - 'atoms': [2861, 2983], - 'data': { - 'score': 11.87 - } -}, { - 'atoms': [3992, 4159], - 'data': { - 'score': 11.79 - } -}, { - 'atoms': [949, 1258], - 'data': { - 'score': 11.75 - } -}, { - 'atoms': [1517, 1546], - 'data': { - 'score': 11.74 - } -}, { - 'atoms': [2687, 2937], - 'data': { - 'score': 11.71 - } -}, { - 'atoms': [2065, 2350], - 'data': { - 'score': 11.6 - } -}, { - 'atoms': [4026, 4159], - 'data': { - 'score': 11.59 - } -}, { - 'atoms': [2065, 2301], - 'data': { - 'score': 11.59 - } -}, { - 'atoms': [3368, 3421], - 'data': { - 'score': 11.56 - } -}, { - 'atoms': [1668, 2767], - 'data': { - 'score': 11.53 - } -}, { - 'atoms': [988, 1290], - 'data': { - 'score': 11.52 - } -}, { - 'atoms': [3753, 3936], - 'data': { - 'score': 11.51 - } -}, { - 'atoms': [1223, 1565], - 'data': { - 'score': 11.46 - } -}, { - 'atoms': [69, 377], - 'data': { - 'score': 11.43 - } -}, { - 'atoms': [4340, 4433], - 'data': { - 'score': 11.39 - } -}, { - 'atoms': [3987, 4159], - 'data': { - 'score': 11.3 - } -}, { - 'atoms': [2679, 3508], - 'data': { - 'score': 11.29 - } -}, { - 'atoms': [2056, 3121], - 'data': { - 'score': 11.25 - } -}, { - 'atoms': [2523, 2767], - 'data': { - 'score': 11.21 - } -}, { - 'atoms': [3762, 4463], - 'data': { - 'score': 11.2 - } -}, { - 'atoms': [3287, 3908], - 'data': { - 'score': 11.15 - } -}, { - 'atoms': [49, 470], - 'data': { - 'score': 11.11 - } -}, { - 'atoms': [49, 1048], - 'data': { - 'score': 11.07 - } -}, { - 'atoms': [2051, 2065], - 'data': { - 'score': 11.04 - } -}, { - 'atoms': [2528, 2795], - 'data': { - 'score': 10.99 - } -}, { - 'atoms': [2065, 2239], - 'data': { - 'score': 10.96 - } -}, { - 'atoms': [2065, 2342], - 'data': { - 'score': 10.92 - } -}, { - 'atoms': [1608, 3604], - 'data': { - 'score': 10.91 - } -}, { - 'atoms': [49, 1258], - 'data': { - 'score': 10.9 - } -}, { - 'atoms': [1497, 1591], - 'data': { - 'score': 10.8 - } -}, { - 'atoms': [4519, 4541], - 'data': { - 'score': 10.77 - } -}, { - 'atoms': [1215, 1565], - 'data': { - 'score': 10.77 - } -}, { - 'atoms': [3441, 3456], - 'data': { - 'score': 10.72 - } -}, { - 'atoms': [4001, 4168], - 'data': { - 'score': 10.69 - } -}, { - 'atoms': [3924, 4256], - 'data': { - 'score': 10.55 - } -}, { - 'atoms': [1432, 1565], - 'data': { - 'score': 10.51 - } -}, { - 'atoms': [1608, 1657], - 'data': { - 'score': 10.45 - } -}, { - 'atoms': [688, 784], - 'data': { - 'score': 10.44 - } -}, { - 'atoms': [4159, 4328], - 'data': { - 'score': 10.41 - } -}, { - 'atoms': [3746, 3762], - 'data': { - 'score': 10.35 - } -}, { - 'atoms': [1457, 1497], - 'data': { - 'score': 10.34 - } -}, { - 'atoms': [955, 1375], - 'data': { - 'score': 10.33 - } -}, { - 'atoms': [3183, 3401], - 'data': { - 'score': 10.28 - } -}, { - 'atoms': [49, 1278], - 'data': { - 'score': 10.24 - } -}, { - 'atoms': [69, 1290], - 'data': { - 'score': 10.11 - } -}, { - 'atoms': [3441, 3477], - 'data': { - 'score': 10.09 - } -}, { - 'atoms': [1040, 1066], - 'data': { - 'score': 10.05 - } -}, { - 'atoms': [2767, 3762], - 'data': { - 'score': 10.05 - } -}, { - 'atoms': [1, 419], - 'data': { - 'score': 9.94 - } -}, { - 'atoms': [1565, 2301], - 'data': { - 'score': 9.88 - } -}, { - 'atoms': [2537, 2804], - 'data': { - 'score': 9.86 - } -}, { - 'atoms': [4328, 4541], - 'data': { - 'score': 9.83 - } -}, { - 'atoms': [1048, 1066], - 'data': { - 'score': 9.8 - } -}, { - 'atoms': [107, 1258], - 'data': { - 'score': 9.79 - } -}, { - 'atoms': [3278, 3900], - 'data': { - 'score': 9.75 - } -}, { - 'atoms': [60, 406], - 'data': { - 'score': 9.74 - } -}, { - 'atoms': [1617, 2767], - 'data': { - 'score': 9.71 - } -}, { - 'atoms': [3943, 4019], - 'data': { - 'score': 9.68 - } -}, { - 'atoms': [2835, 2972], - 'data': { - 'score': 9.63 - } -}, { - 'atoms': [49, 1290], - 'data': { - 'score': 9.57 - } -}, { - 'atoms': [4403, 4463], - 'data': { - 'score': 9.37 - } -}, { - 'atoms': [1448, 3571], - 'data': { - 'score': 9.33 - } -}, { - 'atoms': [2662, 3421], - 'data': { - 'score': 9.31 - } -}, { - 'atoms': [1, 49], - 'data': { - 'score': 9.29 - } -}, { - 'atoms': [3296, 3421], - 'data': { - 'score': 9.27 - } -}, { - 'atoms': [60, 949], - 'data': { - 'score': 9.17 - } -}, { - 'atoms': [1517, 1565], - 'data': { - 'score': 9.15 - } -}, { - 'atoms': [3421, 3477], - 'data': { - 'score': 9.11 - } -}, { - 'atoms': [4052, 4177], - 'data': { - 'score': 9.11 - } -}, { - 'atoms': [3113, 3468], - 'data': { - 'score': 9.11 - } -}, { - 'atoms': [503, 550], - 'data': { - 'score': 9.07 - } -}, { - 'atoms': [2528, 2818], - 'data': { - 'score': 9.06 - } -}, { - 'atoms': [1057, 1290], - 'data': { - 'score': 8.93 - } -}, { - 'atoms': [4256, 4277], - 'data': { - 'score': 8.9 - } -}, { - 'atoms': [2826, 2911], - 'data': { - 'score': 8.75 - } -}, { - 'atoms': [1497, 3384], - 'data': { - 'score': 8.67 - } -}, { - 'atoms': [3121, 3421], - 'data': { - 'score': 8.64 - } -}, { - 'atoms': [529, 564], - 'data': { - 'score': 8.5 - } -}, { - 'atoms': [60, 1299], - 'data': { - 'score': 8.49 - } -}, { - 'atoms': [3917, 4256], - 'data': { - 'score': 8.48 - } -}, { - 'atoms': [1493, 1517], - 'data': { - 'score': 8.39 - } -}, { - 'atoms': [1511, 1557], - 'data': { - 'score': 8.31 - } -}, { - 'atoms': [1506, 1565], - 'data': { - 'score': 8.3 - } -}, { - 'atoms': [1432, 3421], - 'data': { - 'score': 8.3 - } -}, { - 'atoms': [60, 399], - 'data': { - 'score': 8.29 - } -}, { - 'atoms': [3924, 4272], - 'data': { - 'score': 8.26 - } -}, { - 'atoms': [1497, 3430], - 'data': { - 'score': 8.24 - } -}, { - 'atoms': [2662, 3774], - 'data': { - 'score': 8.19 - } -}, { - 'atoms': [60, 1304], - 'data': { - 'score': 7.88 - } -}, { - 'atoms': [1497, 3707], - 'data': { - 'score': 7.6 - } -}, { - 'atoms': [3150, 3421], - 'data': { - 'score': 7.46 - } -}, { - 'atoms': [3332, 3421], - 'data': { - 'score': 7.41 - } -}, { - 'atoms': [2687, 3503], - 'data': { - 'score': 6.81 - } -}] - -var reps = {} // store ngl representations - -// make a map of the links accessible by atom indices for use in colour scheme stuff -var linkMap = {} -links.forEach(function (link) { - var atoms = link.atoms - linkMap[atoms[0] + '-' + atoms[1]] = link -}) - -// make a colour scheme that grabs the score of each link and uses it to return a colour -var initColourSchemes = function () { - var linkColourScheme = function () { - var colCache = {} - - this.bondColor = function (b) { - var origLink = linkMap[b.atomIndex1 + '-' + b.atomIndex2] - - if (origLink) { - var score = origLink.data.score - var col24bit = colCache[score] - if (col24bit === undefined) { - var i = score < valStops[1] ? 1 : 2 - var pct = (score - valStops[i - 1]) / (valStops[i] - valStops[i - 1]) - var col3 = {} - // aargh semi-colon needed at start of line - ;['r', 'g', 'b'].forEach(function (chan) { - col3[chan] = colStops[i - 1][chan] + (colStops[i][chan] - colStops[i - 1][chan]) * pct - }) - col24bit = col3 ? (col3.r << 16) + (col3.g << 8) + col3.b : 255 - colCache[score] = col24bit - } - return col24bit - } - return (128 << 16) + (128 << 8) + 128 // grey default - } - } - - reps.linkColourScheme = NGL.ColormakerRegistry.addScheme(linkColourScheme, 'xlink') -} -initColourSchemes() - -// return unique atom indices as a selection from a set of pairs of atom indices -var makeAtomSelection = function (someLinks) { - var atomSet = new Set() - someLinks.forEach(function (link) { - atomSet.add(link.atoms[0]) - atomSet.add(link.atoms[1]) - }) - var atomSelection = '@' + Array.from(atomSet).join(',') - return atomSelection -} - -// calculate extremes of score distribution for setting up initial slider and colour scale values -var min = Number.POSITIVE_INFINITY -var max = Number.NEGATIVE_INFINITY -links.forEach(function (link) { - var score = link.data.score - if (score !== undefined && score < min) { min = score } - if (score !== undefined && score > max) { max = score } -}) -document.getElementById('scoreSlider').min = min -document.getElementById('scoreSlider').max = max + 1 -document.getElementById('minValue').textContent = min -document.getElementById('maxValue').textContent = max + 1 - -var colStops = [{r: 0, g: 0, b: 128}, {r: 128, g: 255, b: 255}, {r: 255, g: 255, b: 0}] -var valStops = [min, (min + max) / 2, max] - -// listener for dragging slider, filter out links with score values smaller than slider value -document.getElementById('scoreSlider').addEventListener('input', function (evt) { - var val = +evt.target.value - var filteredLinks = links.filter(function (link) { - return link.data.score >= val - }) - reps.links.setParameters({ - atomPair: filteredLinks.map(function (fl) { - return fl.atoms - }) - }) - reps.residues.setSelection(makeAtomSelection(filteredLinks)) -}) - -// initial atom selection for residues -var startAtomSel = makeAtomSelection(links) - -// load pdb file and set up representations -stage.loadFile('rcsb://1AO6', { - sele: ':A' -}).then(function (o) { // restrict to 1 chain cos links are on the monomer - o.addRepresentation('cartoon', { - color: '#666' - }) - - var baseLinkScale = 3 - - reps.links = o.addRepresentation('distance', { - atomPair: links.map(function (l) { - return l.atoms - }), - // colorValue: 'yellow', - colorScheme: reps.linkColourScheme, - labelSize: 4, - labelColor: 'white', - labelVisible: true, - labelUnit: 'angstrom', - radiusScale: baseLinkScale, - opacity: 1, - name: 'link', - side: 'front', - useCylinder: true - }) - - reps.residues = o.addRepresentation('spacefill', { - sele: startAtomSel, - color: '#ccc', - // colorScale: ['#44f', '#444'], - radiusScale: 0.6, - name: 'res' - }) - - o.autoView(':A') // center on chain A -}) diff --git a/examples/examples/scripts/interactive/hover-tooltip.js b/examples/examples/scripts/interactive/hover-tooltip.js deleted file mode 100644 index f98890d06..000000000 --- a/examples/examples/scripts/interactive/hover-tooltip.js +++ /dev/null @@ -1,34 +0,0 @@ - -// create tooltip element and add to document body -var tooltip = document.createElement('div') -Object.assign(tooltip.style, { - display: 'none', - position: 'fixed', - zIndex: 10, - pointerEvents: 'none', - backgroundColor: 'rgba( 0, 0, 0, 0.6 )', - color: 'lightgrey', - padding: '8px', - fontFamily: 'sans-serif' -}) -document.body.appendChild(tooltip) - -// load a structure file -stage.loadFile('data://1blu.mmtf', { defaultRepresentation: true }) - -// remove default hoverPick mouse action -stage.mouseControls.remove('hoverPick') - -// listen to `hovered` signal to move tooltip around and change its text -stage.signals.hovered.add(function (pickingProxy) { - if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) { - var atom = pickingProxy.atom || pickingProxy.closestBondAtom - var mp = pickingProxy.mouse.position - tooltip.innerText = 'ATOM: ' + atom.qualifiedName() - tooltip.style.bottom = window.innerHeight - mp.y + 3 + 'px' - tooltip.style.left = mp.x + 3 + 'px' - tooltip.style.display = 'block' - } else { - tooltip.style.display = 'none' - } -}) diff --git a/examples/examples/scripts/interactive/interpolate.js b/examples/examples/scripts/interactive/interpolate.js deleted file mode 100644 index 204506088..000000000 --- a/examples/examples/scripts/interactive/interpolate.js +++ /dev/null @@ -1,20 +0,0 @@ - -stage.loadFile('data://lig0FG.2models.pdb', { - asTrajectory: true -}).then(function (o) { - var traj = o.addTrajectory().trajectory - var player = new NGL.TrajectoryPlayer(traj, { - step: 1, - timeout: 70, - interpolateStep: 100, - start: 0, - end: traj.numframes, - interpolateType: 'linear', - mode: 'once', - direction: 'bounce' - }) - player.play() - - o.addRepresentation('licorice') - o.autoView() -}) diff --git a/examples/examples/scripts/interactive/ligand-viewer.js b/examples/examples/scripts/interactive/ligand-viewer.js deleted file mode 100644 index 2a67e0f92..000000000 --- a/examples/examples/scripts/interactive/ligand-viewer.js +++ /dev/null @@ -1,627 +0,0 @@ - -stage.setParameters({ - backgroundColor: 'white' -}) - -function addElement (el) { - Object.assign(el.style, { - position: 'absolute', - zIndex: 10 - }) - stage.viewer.container.appendChild(el) -} - -function createElement (name, properties, style) { - var el = document.createElement(name) - Object.assign(el, properties) - Object.assign(el.style, style) - return el -} - -function createSelect (options, properties, style) { - var select = createElement('select', properties, style) - options.forEach(function (d) { - select.add(createElement('option', { - value: d[ 0 ], text: d[ 1 ] - })) - }) - return select -} - -function createFileButton (label, properties, style) { - var input = createElement('input', Object.assign({ - type: 'file' - }, properties), { display: 'none' }) - addElement(input) - var button = createElement('input', { - value: label, - type: 'button', - onclick: function () { input.click() } - }, style) - return button -} - -var topPosition = 12 - -function getTopPosition (increment) { - if (increment) topPosition += increment - return topPosition + 'px' -} - -// create tooltip element and add to document body -var tooltip = document.createElement('div') -Object.assign(tooltip.style, { - display: 'none', - position: 'fixed', - zIndex: 10, - pointerEvents: 'none', - backgroundColor: 'rgba( 0, 0, 0, 0.6 )', - color: 'lightgrey', - padding: '8px', - fontFamily: 'sans-serif' -}) -document.body.appendChild(tooltip) - -// remove default hoverPick mouse action -stage.mouseControls.remove('hoverPick') - -// listen to `hovered` signal to move tooltip around and change its text -stage.signals.hovered.add(function (pickingProxy) { - if (pickingProxy) { - if (pickingProxy.atom || pickingProxy.bond) { - var atom = pickingProxy.atom || pickingProxy.closestBondAtom - var vm = atom.structure.data['@valenceModel'] - if (vm && vm.idealValence) { - tooltip.innerHTML = `${pickingProxy.getLabel()}
-
- Atom: ${atom.qualifiedName()}
- ideal valence: ${vm.idealValence[atom.index]}
- ideal geometry: ${vm.idealGeometry[atom.index]}
- implicit charge: ${vm.implicitCharge[atom.index]}
- formal charge: ${atom.formalCharge === null ? '?' : atom.formalCharge}
- aromatic: ${atom.aromatic ? 'true' : 'false'}
- ` - } else if (vm && vm.charge) { - tooltip.innerHTML = `${pickingProxy.getLabel()}
-
- Atom: ${atom.qualifiedName()}
- vm charge: ${vm.charge[atom.index]}
- vm implicitH: ${vm.implicitH[atom.index]}
- vm totalH: ${vm.totalH[atom.index]}
- vm geom: ${vm.idealGeometry[atom.index]}
- formal charge: ${atom.formalCharge === null ? '?' : atom.formalCharge}
- aromatic: ${atom.aromatic ? 'true' : 'false'}
- ` - } else { - tooltip.innerHTML = `${pickingProxy.getLabel()}` - } - } else { - tooltip.innerHTML = `${pickingProxy.getLabel()}` - } - var mp = pickingProxy.mouse.position - tooltip.style.bottom = window.innerHeight - mp.y + 3 + 'px' - tooltip.style.left = mp.x + 3 + 'px' - tooltip.style.display = 'block' - } else { - tooltip.style.display = 'none' - } -}) - -stage.signals.clicked.add(function (pickingProxy) { - if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) { - console.log(pickingProxy.atom || pickingProxy.closestBondAtom) - } -}) - -var ligandSele = '( not polymer or not ( protein or nucleic ) ) and not ( water or ACE or NH2 )' - -var pocketRadius = 0 -var pocketRadiusClipFactor = 1 - -var cartoonRepr, backboneRepr, spacefillRepr, neighborRepr, ligandRepr, contactRepr, pocketRepr, labelRepr - -var struc -var neighborSele -var sidechainAttached = false - -function loadStructure (input) { - struc = undefined - stage.setFocus(0) - stage.removeAllComponents() - ligandSelect.innerHTML = '' - clipNearRange.value = 0 - clipRadiusRange.value = 100 - pocketOpacityRange.value = 0 - cartoonCheckbox.checked = false - backboneCheckbox.checked = false - hydrogenCheckbox.checked = true - hydrophobicCheckbox.checked = false - hydrogenBondCheckbox.checked = true - weakHydrogenBondCheckbox.checked = false - waterHydrogenBondCheckbox.checked = true - backboneHydrogenBondCheckbox.checked = true - halogenBondCheckbox.checked = true - metalInteractionCheckbox.checked = true - saltBridgeCheckbox.checked = true - cationPiCheckbox.checked = true - piStackingCheckbox.checked = true - return stage.loadFile(input).then(function (o) { - struc = o - setLigandOptions() - setChainOptions() - setResidueOptions() - o.autoView() - cartoonRepr = o.addRepresentation('cartoon', { - visible: false - }) - backboneRepr = o.addRepresentation('backbone', { - visible: true, - colorValue: 'lightgrey', - radiusScale: 2 - }) - spacefillRepr = o.addRepresentation('spacefill', { - sele: ligandSele, - visible: true - }) - neighborRepr = o.addRepresentation('ball+stick', { - sele: 'none', - aspectRatio: 1.1, - colorValue: 'lightgrey', - multipleBond: 'symmetric' - }) - ligandRepr = o.addRepresentation('ball+stick', { - multipleBond: 'symmetric', - colorValue: 'grey', - sele: 'none', - aspectRatio: 1.2, - radiusScale: 2.5 - }) - contactRepr = o.addRepresentation('contact', { - sele: 'none', - radiusSize: 0.07, - weakHydrogenBond: false, - waterHydrogenBond: false, - backboneHydrogenBond: true - }) - pocketRepr = o.addRepresentation('surface', { - sele: 'none', - lazy: true, - visibility: true, - clipNear: 0, - opaqueBack: false, - opacity: 0.0, - color: 'hydrophobicity', - roughness: 1.0, - surfaceType: 'av' - }) - labelRepr = o.addRepresentation('label', { - sele: 'none', - color: '#333333', - yOffset: 0.2, - zOffset: 2.0, - attachment: 'bottom-center', - showBorder: true, - borderColor: 'lightgrey', - borderWidth: 0.25, - disablePicking: true, - radiusType: 'size', - radiusSize: 0.8, - labelType: 'residue', - labelGrouping: 'residue' - }) - }) -} - -function setLigandOptions () { - ligandSelect.innerHTML = '' - var options = [['', 'select ligand']] - struc.structure.eachResidue(function (rp) { - if (rp.isWater()) return - var sele = '' - if (rp.resno !== undefined) sele += rp.resno - if (rp.inscode) sele += '^' + rp.inscode - if (rp.chain) sele += ':' + rp.chainname - var name = (rp.resname ? '[' + rp.resname + ']' : '') + sele - if (rp.entity && rp.entity.description) name += ' (' + rp.entity.description + ')' - options.push([sele, name]) - }, new NGL.Selection(ligandSele)) - options.forEach(function (d) { - ligandSelect.add(createElement('option', { - value: d[0], text: d[1] - })) - }) -} - -function setChainOptions () { - chainSelect.innerHTML = '' - var options = [['', 'select chain']] - struc.structure.eachChain(function (cp) { - var name = cp.chainname - if (cp.entity && cp.entity.description) name += ' (' + cp.entity.description + ')' - options.push([cp.chainname, name]) - }, new NGL.Selection('polymer')) - options.forEach(function (d) { - chainSelect.add(createElement('option', { - value: d[0], text: d[1] - })) - }) -} - -function setResidueOptions (chain) { - residueSelect.innerHTML = '' - var options = [['', 'select residue']] - if (chain) { - struc.structure.eachResidue(function (rp) { - var sele = '' - if (rp.resno !== undefined) sele += rp.resno - if (rp.inscode) sele += '^' + rp.inscode - if (rp.chain) sele += ':' + rp.chainname - var name = (rp.resname ? '[' + rp.resname + ']' : '') + sele - options.push([sele, name]) - }, new NGL.Selection('polymer and :' + chain)) - } - options.forEach(function (d) { - residueSelect.add(createElement('option', { - value: d[0], text: d[1] - })) - }) -} - -var loadStructureButton = createFileButton('load structure', { - accept: '.pdb,.cif,.ent,.gz,.mol2', - onchange: function (e) { - if (e.target.files[ 0 ]) { - loadStructure(e.target.files[ 0 ]) - } - } -}, { top: getTopPosition(), left: '12px' }) -addElement(loadStructureButton) - -var loadPdbidText = createElement('span', { - innerText: 'load pdb id' -}, { top: getTopPosition(20), left: '12px', color: 'grey' }) -addElement(loadPdbidText) - -var loadPdbidInput = createElement('input', { - type: 'text', - title: 'press enter to load pdbid', - onkeypress: function (e) { - if (e.keyCode === 13) { - e.preventDefault() - loadStructure('rcsb://' + e.target.value) - } - } -}, { top: getTopPosition(20), left: '12px', width: '120px' }) -addElement(loadPdbidInput) - -function showFull () { - ligandSelect.value = '' - - backboneRepr.setParameters({ radiusScale: 2 }) - backboneRepr.setVisibility(true) - spacefillRepr.setVisibility(true) - - ligandRepr.setVisibility(false) - neighborRepr.setVisibility(false) - contactRepr.setVisibility(false) - pocketRepr.setVisibility(false) - labelRepr.setVisibility(false) - - struc.autoView(2000) -} - -var fullButton = createElement('input', { - value: 'full structure', - type: 'button', - onclick: showFull -}, { top: getTopPosition(30), left: '12px' }) -addElement(fullButton) - -function showLigand (sele) { - var s = struc.structure - - var withinSele = s.getAtomSetWithinSelection(new NGL.Selection(sele), 5) - var withinGroup = s.getAtomSetWithinGroup(withinSele) - var expandedSele = withinGroup.toSeleString() - // neighborSele = '(' + expandedSele + ') and not (' + sele + ')' - neighborSele = expandedSele - - var sview = s.getView(new NGL.Selection(sele)) - pocketRadius = Math.max(sview.boundingBox.getSize(new NGL.Vector3()).length() / 2, 2) + 5 - var withinSele2 = s.getAtomSetWithinSelection(new NGL.Selection(sele), pocketRadius + 2) - var neighborSele2 = '(' + withinSele2.toSeleString() + ') and not (' + sele + ') and polymer' - - backboneRepr.setParameters({ radiusScale: 0.2 }) - backboneRepr.setVisibility(backboneCheckbox.checked) - spacefillRepr.setVisibility(false) - - ligandRepr.setVisibility(true) - neighborRepr.setVisibility(true) - contactRepr.setVisibility(true) - pocketRepr.setVisibility(true) - labelRepr.setVisibility(labelCheckbox.checked) - - ligandRepr.setSelection(sele) - neighborRepr.setSelection( - sidechainAttached ? '(' + neighborSele + ') and (sidechainAttached or not polymer)' : neighborSele - ) - contactRepr.setSelection(expandedSele) - pocketRepr.setSelection(neighborSele2) - pocketRepr.setParameters({ - clipRadius: pocketRadius * pocketRadiusClipFactor, - clipCenter: sview.center - }) - labelRepr.setSelection('(' + neighborSele + ') and not (water or ion)') - - struc.autoView(expandedSele, 2000) -} - -var ligandSelect = createSelect([], { - onchange: function (e) { - residueSelect.value = '' - var sele = e.target.value - if (!sele) { - showFull() - } else { - showLigand(sele) - } - } -}, { top: getTopPosition(30), left: '12px', width: '130px' }) -addElement(ligandSelect) - -var chainSelect = createSelect([], { - onchange: function (e) { - ligandSelect.value = '' - residueSelect.value = '' - setResidueOptions(e.target.value) - } -}, { top: getTopPosition(20), left: '12px', width: '130px' }) -addElement(chainSelect) - -var residueSelect = createSelect([], { - onchange: function (e) { - ligandSelect.value = '' - var sele = e.target.value - if (!sele) { - showFull() - } else { - showLigand(sele) - } - } -}, { top: getTopPosition(20), left: '12px', width: '130px' }) -addElement(residueSelect) - -addElement(createElement('span', { - innerText: 'pocket near clipping' -}, { top: getTopPosition(30), left: '12px', color: 'grey' })) -var clipNearRange = createElement('input', { - type: 'range', value: 0, min: 0, max: 10000, step: 1 -}, { top: getTopPosition(16), left: '12px' }) -clipNearRange.oninput = function (e) { - var sceneRadius = stage.viewer.boundingBox.getSize(new NGL.Vector3()).length() / 2 - - var f = pocketRadius / sceneRadius - var v = parseFloat(e.target.value) / 10000 // must be between 0 and 1 - var c = 0.5 - f / 2 + v * f - - pocketRepr.setParameters({ - clipNear: c * 100 // must be between 0 and 100 - }) -} -addElement(clipNearRange) - -addElement(createElement('span', { - innerText: 'pocket radius clipping' -}, { top: getTopPosition(20), left: '12px', color: 'grey' })) -var clipRadiusRange = createElement('input', { - type: 'range', value: 100, min: 1, max: 100, step: 1 -}, { top: getTopPosition(16), left: '12px' }) -clipRadiusRange.oninput = function (e) { - pocketRadiusClipFactor = parseFloat(e.target.value) / 100 - pocketRepr.setParameters({ clipRadius: pocketRadius * pocketRadiusClipFactor }) -} -addElement(clipRadiusRange) - -addElement(createElement('span', { - innerText: 'pocket opacity' -}, { top: getTopPosition(20), left: '12px', color: 'grey' })) -var pocketOpacityRange = createElement('input', { - type: 'range', value: 90, min: 0, max: 100, step: 1 -}, { top: getTopPosition(16), left: '12px' }) -pocketOpacityRange.oninput = function (e) { - pocketRepr.setParameters({ - opacity: parseFloat(e.target.value) / 100 - }) -} -addElement(pocketOpacityRange) - -var cartoonCheckbox = createElement('input', { - type: 'checkbox', - checked: false, - onchange: function (e) { - cartoonRepr.setVisibility(e.target.checked) - } -}, { top: getTopPosition(30), left: '12px' }) -addElement(cartoonCheckbox) -addElement(createElement('span', { - innerText: 'cartoon' -}, { top: getTopPosition(), left: '32px', color: 'grey' })) - -var backboneCheckbox = createElement('input', { - type: 'checkbox', - checked: false, - onchange: function (e) { - backboneRepr.setVisibility(e.target.checked) - } -}, { top: getTopPosition(20), left: '12px' }) -addElement(backboneCheckbox) -addElement(createElement('span', { - innerText: 'backbone' -}, { top: getTopPosition(), left: '32px', color: 'grey' })) - -var hydrogenCheckbox = createElement('input', { - type: 'checkbox', - checked: true, - onchange: function (e) { - if (e.target.checked) { - struc.setSelection('*') - } else { - struc.setSelection('not _H') - } - } -}, { top: getTopPosition(20), left: '12px' }) -addElement(hydrogenCheckbox) -addElement(createElement('span', { - innerText: 'hydrogen' -}, { top: getTopPosition(), left: '32px', color: 'grey' })) - -var sidechainAttachedCheckbox = createElement('input', { - type: 'checkbox', - checked: false, - onchange: function (e) { - sidechainAttached = e.target.checked - neighborRepr.setSelection( - sidechainAttached ? '(' + neighborSele + ') and (sidechainAttached or not polymer)' : neighborSele - ) - } -}, { top: getTopPosition(20), left: '12px' }) -addElement(sidechainAttachedCheckbox) -addElement(createElement('span', { - innerText: 'sidechainAttached' -}, { top: getTopPosition(), left: '32px', color: 'grey' })) - -var labelCheckbox = createElement('input', { - type: 'checkbox', - checked: true, - onchange: function (e) { - labelRepr.setVisibility(e.target.checked) - } -}, { top: getTopPosition(20), left: '12px' }) -addElement(labelCheckbox) -addElement(createElement('span', { - innerText: 'label' -}, { top: getTopPosition(), left: '32px', color: 'grey' })) - -var hydrophobicCheckbox = createElement('input', { - type: 'checkbox', - checked: false, - onchange: function (e) { - contactRepr.setParameters({ hydrophobic: e.target.checked }) - } -}, { top: getTopPosition(30), left: '12px' }) -addElement(hydrophobicCheckbox) -addElement(createElement('span', { - innerText: 'hydrophobic' -}, { top: getTopPosition(), left: '32px', color: 'grey' })) - -var hydrogenBondCheckbox = createElement('input', { - type: 'checkbox', - checked: false, - onchange: function (e) { - contactRepr.setParameters({ hydrogenBond: e.target.checked }) - } -}, { top: getTopPosition(20), left: '12px' }) -addElement(hydrogenBondCheckbox) -addElement(createElement('span', { - innerText: 'hbond' -}, { top: getTopPosition(), left: '32px', color: 'grey' })) - -var weakHydrogenBondCheckbox = createElement('input', { - type: 'checkbox', - checked: false, - onchange: function (e) { - contactRepr.setParameters({ weakHydrogenBond: e.target.checked }) - } -}, { top: getTopPosition(20), left: '12px' }) -addElement(weakHydrogenBondCheckbox) -addElement(createElement('span', { - innerText: 'weak hbond' -}, { top: getTopPosition(), left: '32px', color: 'grey' })) - -var waterHydrogenBondCheckbox = createElement('input', { - type: 'checkbox', - checked: false, - onchange: function (e) { - contactRepr.setParameters({ waterHydrogenBond: e.target.checked }) - } -}, { top: getTopPosition(20), left: '12px' }) -addElement(waterHydrogenBondCheckbox) -addElement(createElement('span', { - innerText: 'water-water hbond' -}, { top: getTopPosition(), left: '32px', color: 'grey' })) - -var backboneHydrogenBondCheckbox = createElement('input', { - type: 'checkbox', - checked: false, - onchange: function (e) { - contactRepr.setParameters({ backboneHydrogenBond: e.target.checked }) - } -}, { top: getTopPosition(20), left: '12px' }) -addElement(backboneHydrogenBondCheckbox) -addElement(createElement('span', { - innerText: 'backbone-backbone hbond' -}, { top: getTopPosition(), left: '32px', color: 'grey' })) - -var halogenBondCheckbox = createElement('input', { - type: 'checkbox', - checked: true, - onchange: function (e) { - contactRepr.setParameters({ halogenBond: e.target.checked }) - } -}, { top: getTopPosition(20), left: '12px' }) -addElement(halogenBondCheckbox) -addElement(createElement('span', { - innerText: 'halogen bond' -}, { top: getTopPosition(), left: '32px', color: 'grey' })) - -var metalInteractionCheckbox = createElement('input', { - type: 'checkbox', - checked: true, - onchange: function (e) { - contactRepr.setParameters({ metalComplex: e.target.checked }) - } -}, { top: getTopPosition(20), left: '12px' }) -addElement(metalInteractionCheckbox) -addElement(createElement('span', { - innerText: 'metal interaction' -}, { top: getTopPosition(), left: '32px', color: 'grey' })) - -var saltBridgeCheckbox = createElement('input', { - type: 'checkbox', - checked: true, - onchange: function (e) { - contactRepr.setParameters({ saltBridge: e.target.checked }) - } -}, { top: getTopPosition(20), left: '12px' }) -addElement(saltBridgeCheckbox) -addElement(createElement('span', { - innerText: 'salt bridge' -}, { top: getTopPosition(), left: '32px', color: 'grey' })) - -var cationPiCheckbox = createElement('input', { - type: 'checkbox', - checked: true, - onchange: function (e) { - contactRepr.setParameters({ cationPi: e.target.checked }) - } -}, { top: getTopPosition(20), left: '12px' }) -addElement(cationPiCheckbox) -addElement(createElement('span', { - innerText: 'cation-pi' -}, { top: getTopPosition(), left: '32px', color: 'grey' })) - -var piStackingCheckbox = createElement('input', { - type: 'checkbox', - checked: true, - onchange: function (e) { - contactRepr.setParameters({ piStacking: e.target.checked }) - } -}, { top: getTopPosition(20), left: '12px' }) -addElement(piStackingCheckbox) -addElement(createElement('span', { - innerText: 'pi-stacking' -}, { top: getTopPosition(), left: '32px', color: 'grey' })) - -loadStructure('rcsb://4cup').then(function () { - showLigand('ZYB') -}) diff --git a/examples/examples/scripts/interactive/simple-viewer.js b/examples/examples/scripts/interactive/simple-viewer.js deleted file mode 100644 index 87cbeb294..000000000 --- a/examples/examples/scripts/interactive/simple-viewer.js +++ /dev/null @@ -1,125 +0,0 @@ - -function addElement (el) { - Object.assign(el.style, { - position: 'absolute', - zIndex: 10 - }) - stage.viewer.container.appendChild(el) -} - -function createElement (name, properties, style) { - var el = document.createElement(name) - Object.assign(el, properties) - Object.assign(el.style, style) - return el -} - -function createSelect (options, properties, style) { - var select = createElement('select', properties, style) - options.forEach(function (d) { - select.add(createElement('option', { - value: d[ 0 ], text: d[ 1 ] - })) - }) - return select -} - -function createFileButton (label, properties, style) { - var input = createElement('input', Object.assign({ - type: 'file' - }, properties), { display: 'none' }) - addElement(input) - var button = createElement('input', { - value: label, - type: 'button', - onclick: function () { input.click() } - }, style) - return button -} - -function loadStructure (input) { - stage.removeAllComponents() - return stage.loadFile(input).then(function (o) { - o.autoView() - o.addRepresentation(polymerSelect.value, { - sele: 'polymer', - name: 'polymer' - }) - o.addRepresentation('ball+stick', { - name: 'ligand', - visible: ligandCheckbox.checked, - sele: 'not ( polymer or water or ion )' - }) - o.addRepresentation('spacefill', { - name: 'waterIon', - visible: waterIonCheckbox.checked, - sele: 'water or ion', - scale: 0.25 - }) - }) -} - -var loadStructureButton = createFileButton('load structure', { - accept: '.pdb,.cif,.ent,.gz', - onchange: function (e) { - if (e.target.files[ 0 ]) { - loadStructure(e.target.files[ 0 ]) - } - } -}, { top: '12px', left: '12px' }) -addElement(loadStructureButton) - -var polymerSelect = createSelect([ - [ 'cartoon', 'cartoon' ], - [ 'spacefill', 'spacefill' ], - [ 'licorice', 'licorice' ], - [ 'surface', 'surface' ] -], { - onchange: function (e) { - stage.getRepresentationsByName('polymer').dispose() - stage.eachComponent(function (o) { - o.addRepresentation(e.target.value, { - sele: 'polymer', - name: 'polymer' - }) - }) - } -}, { top: '36px', left: '12px' }) -addElement(polymerSelect) - -var ligandCheckbox = createElement('input', { - type: 'checkbox', - checked: true, - onchange: function (e) { - stage.getRepresentationsByName('ligand') - .setVisibility(e.target.checked) - } -}, { top: '60px', left: '12px' }) -addElement(ligandCheckbox) -addElement(createElement('span', { - innerText: 'ligand' -}, { top: '60px', left: '32px' })) - -var waterIonCheckbox = createElement('input', { - type: 'checkbox', - checked: false, - onchange: function (e) { - stage.getRepresentationsByName('waterIon') - .setVisibility(e.target.checked) - } -}, { top: '84px', left: '12px' }) -addElement(waterIonCheckbox) -addElement(createElement('span', { - innerText: 'water+ion' -}, { top: '84px', left: '32px' })) - -var centerButton = createElement('input', { - type: 'button', - value: 'center', - onclick: function () { - stage.autoView(1000) - } -}, { top: '108px', left: '12px' }) -addElement(centerButton) - -loadStructure('data://3SN6.cif') diff --git a/examples/examples/scripts/interactive/xray-viewer.js b/examples/examples/scripts/interactive/xray-viewer.js deleted file mode 100644 index 7856dd950..000000000 --- a/examples/examples/scripts/interactive/xray-viewer.js +++ /dev/null @@ -1,455 +0,0 @@ - -var edmapUrl = 'https://edmaps.rcsb.org/maps/' - -stage.setParameters({ - cameraType: 'orthographic', - mousePreset: 'coot' -}) - -function addElement (el) { - Object.assign(el.style, { - position: 'absolute', - zIndex: 10 - }) - stage.viewer.container.appendChild(el) -} - -function createElement (name, properties, style) { - var el = document.createElement(name) - Object.assign(el, properties) - Object.assign(el.style, style) - return el -} - -function createSelect (options, properties, style) { - var select = createElement('select', properties, style) - options.forEach(function (d) { - select.add(createElement('option', { - value: d[ 0 ], text: d[ 1 ] - })) - }) - return select -} - -function createFileButton (label, properties, style) { - var input = createElement('input', Object.assign({ - type: 'file' - }, properties), { display: 'none' }) - addElement(input) - var button = createElement('input', { - value: label, - type: 'button', - onclick: function () { input.click() } - }, style) - return button -} - -var scroll2fofc, scrollFofc - -function isolevelScroll (stage, delta) { - var d = Math.sign(delta) / 10 - stage.eachRepresentation(function (reprElem, comp) { - var p - if (scroll2fofc && reprElem === surf2fofc) { - p = reprElem.getParameters() - reprElem.setParameters({ isolevel: Math.max(0.01, p.isolevel + d) }) - } else if (scrollFofc && (reprElem === surfFofc || reprElem === surfFofcNeg)) { - p = reprElem.getParameters() - reprElem.setParameters({ isolevel: Math.max(0.01, p.isolevel + d) }) - } - }) -} - -stage.mouseControls.add('scroll', isolevelScroll) - -var struc -function loadStructure (input) { - struc = undefined - surf2fofc = undefined - surfFofc = undefined - surfFofcNeg = undefined - file2fofcText.innerText = '2fofc file: none' - fileFofcText.innerText = 'fofc file: none' - isolevel2fofcText.innerText = '' - isolevelFofcText.innerText = '' - boxSizeRange.value = 10 - seleInput.value = '' - stage.setFocus(0) - stage.removeAllComponents() - return stage.loadFile(input).then(function (o) { - fileStructureText.innerText = 'structure file: ' + o.name - struc = o - o.autoView() - o.addRepresentation('line', { - colorValue: 'yellow', - multipleBond: 'offset', - bondSpacing: 1.1, - linewidth: 6 - }) - o.addRepresentation('point', { - colorValue: 'yellow', - sizeAttenuation: false, - pointSize: 6, - alphaTest: 1, - useTexture: true - }) - }) -} - -var surf2fofc -function load2fofc (input) { - return stage.loadFile(input).then(function (o) { - file2fofcText.innerText = '2fofc file: ' + o.name - isolevel2fofcText.innerText = '2fofc level: 1.5\u03C3' - boxSizeRange.value = 10 - scrollSelect.value = '2fofc' - scroll2fofc = true - if (surfFofc) { - isolevelFofcText.innerText = 'fofc level: 3.0\u03C3' - surfFofc.setParameters({ isolevel: 3, boxSize: 10, contour: true, isolevelScroll: false }) - surfFofcNeg.setParameters({ isolevel: 3, boxSize: 10, contour: true, isolevelScroll: false }) - } - surf2fofc = o.addRepresentation('surface', { - color: 'skyblue', - isolevel: 1.5, - boxSize: 10, - useWorker: false, - contour: true, - opaqueBack: false, - isolevelScroll: false - }) - }) -} - -var surfFofc, surfFofcNeg -function loadFofc (input) { - return stage.loadFile(input).then(function (o) { - fileFofcText.innerText = 'fofc file: ' + o.name - isolevelFofcText.innerText = 'fofc level: 3.0\u03C3' - boxSizeRange.value = 10 - scrollSelect.value = '2fofc' - scrollFofc = false - if (surf2fofc) { - isolevel2fofcText.innerText = '2fofc level: 1.5\u03C3' - surf2fofc.setParameters({ isolevel: 1.5, boxSize: 10, contour: true, isolevelScroll: false }) - } - surfFofc = o.addRepresentation('surface', { - color: 'mediumseagreen', - isolevel: 3, - boxSize: 10, - useWorker: false, - contour: true, - opaqueBack: false, - isolevelScroll: false - }) - surfFofcNeg = o.addRepresentation('surface', { - color: 'tomato', - isolevel: 3, - negateIsolevel: true, - boxSize: 10, - useWorker: false, - contour: true, - opaqueBack: false, - isolevelScroll: false - }) - }) -} - -var loadStructureButton = createFileButton('load structure', { - accept: '.pdb,.cif,.ent,.gz', - onchange: function (e) { - if (e.target.files[ 0 ]) { - exampleSelect.value = '' - loadStructure(e.target.files[ 0 ]) - } - } -}, { top: '12px', left: '12px' }) -addElement(loadStructureButton) - -var load2fofcButton = createFileButton('load 2fofc', { - accept: '.map,.ccp4,.brix,.dsn6,.mrc,.gz', - onchange: function (e) { - if (e.target.files[ 0 ]) { - load2fofc(e.target.files[ 0 ]) - } - } -}, { top: '36px', left: '12px' }) -addElement(load2fofcButton) - -var loadFofcButton = createFileButton('load fofc', { - accept: '.map,.ccp4,.brix,.dsn6,.mrc,.gz', - onchange: function (e) { - if (e.target.files[ 0 ]) { - loadFofc(e.target.files[ 0 ]) - } - } -}, { top: '60px', left: '12px' }) -addElement(loadFofcButton) - -var exampleSelect = createSelect([ - [ '', 'load example' ], - [ '3ek3', '3ek3' ], - [ '3nzd', '3nzd' ], - [ '1lee', '1lee' ] -], { - onchange: function (e) { - var id = e.target.value - loadExample(id).then(function () { - if (id === '3nzd') { - seleInput.value = 'NDP' - } else if (id === '1lee') { - seleInput.value = 'R36 and (.C28 or .N1)' - } - applySele(seleInput.value) - }) - } -}, { top: '84px', left: '12px' }) -addElement(exampleSelect) - -var seleText = createElement('span', { - innerText: 'center selection', - title: 'press enter to apply and center' -}, { top: '114px', left: '12px', color: 'lightgrey' }) -addElement(seleText) - -var lastSele -function checkSele (str) { - var selection = new NGL.Selection(str) - return !selection.selection[ 'error' ] -} -function applySele (value) { - if (value) { - lastSele = value - struc.autoView(value) - var z = stage.viewer.camera.position.z - stage.setFocus(100 - Math.abs(z / 10)) - } -} -var seleInput = createElement('input', { - type: 'text', - title: 'press enter to apply and center', - onkeypress: function (e) { - var value = e.target.value - var character = String.fromCharCode(e.which) - if (e.keyCode === 13) { - e.preventDefault() - if (checkSele(value)) { - if (struc) { - applySele(value) - } - e.target.style.backgroundColor = 'white' - } else { - e.target.style.backgroundColor = 'tomato' - } - } else if (lastSele !== value + character) { - e.target.style.backgroundColor = 'skyblue' - } else { - e.target.style.backgroundColor = 'white' - } - } -}, { top: '134px', left: '12px', width: '120px' }) -addElement(seleInput) - -var surfaceSelect = createSelect([ - [ 'contour', 'contour' ], - [ 'wireframe', 'wireframe' ], - [ 'smooth', 'smooth' ], - [ 'flat', 'flat' ] -], { - onchange: function (e) { - var v = e.target.value - var p - if (v === 'contour') { - p = { - contour: true, - flatShaded: false, - opacity: 1, - metalness: 0, - wireframe: false - } - } else if (v === 'wireframe') { - p = { - contour: false, - flatShaded: false, - opacity: 1, - metalness: 0, - wireframe: true - } - } else if (v === 'smooth') { - p = { - contour: false, - flatShaded: false, - opacity: 0.5, - metalness: 0, - wireframe: false - } - } else if (v === 'flat') { - p = { - contour: false, - flatShaded: true, - opacity: 0.5, - metalness: 0.2, - wireframe: false - } - } - stage.getRepresentationsByName('surface').setParameters(p) - } -}, { top: '170px', left: '12px' }) -addElement(surfaceSelect) - -var toggle2fofcButton = createElement('input', { - type: 'button', - value: 'toggle 2fofc', - onclick: function (e) { - surf2fofc.toggleVisibility() - } -}, { top: '194px', left: '12px' }) -addElement(toggle2fofcButton) - -var toggleFofcButton = createElement('input', { - type: 'button', - value: 'toggle fofc', - onclick: function (e) { - surfFofc.toggleVisibility() - surfFofcNeg.toggleVisibility() - } -}, { top: '218px', left: '12px' }) -addElement(toggleFofcButton) - -addElement(createElement('span', { - innerText: 'box size' -}, { top: '242px', left: '12px', color: 'lightgrey' })) -var boxSizeRange = createElement('input', { - type: 'range', - value: 10, - min: 1, - max: 50, - step: 1, - oninput: function (e) { - stage.getRepresentationsByName('surface').setParameters({ - boxSize: parseInt(e.target.value) - }) - } -}, { top: '258px', left: '12px' }) -addElement(boxSizeRange) - -var screenshotButton = createElement('input', { - type: 'button', - value: 'screenshot', - onclick: function () { - stage.makeImage({ - factor: 1, - antialias: false, - trim: false, - transparent: false - }).then(function (blob) { - NGL.download(blob, 'ngl-xray-viewer-screenshot.png') - }) - } -}, { top: '282px', left: '12px' }) -addElement(screenshotButton) - -var scrollSelect = createSelect([ - [ '2fofc', 'scroll 2fofc' ], - [ 'fofc', 'scroll fofc' ], - [ 'both', 'scroll both' ] -], { - onchange: function (e) { - var v = e.target.value - if (v === '2fofc') { - scroll2fofc = true - scrollFofc = false - } else if (v === 'fofc') { - scroll2fofc = false - scrollFofc = true - } else if (v === 'both') { - scroll2fofc = true - scrollFofc = true - } - } -}, { top: '306px', left: '12px' }) -addElement(scrollSelect) - -var loadEdmapText = createElement('span', { - innerText: 'load edmap for pdb id', - title: 'press enter to load' -}, { top: '330px', left: '12px', color: 'lightgrey' }) -addElement(loadEdmapText) - -var loadEdmapInput = createElement('input', { - type: 'text', - title: 'press enter to load', - onkeypress: function (e) { - var value = e.target.value - if (e.keyCode === 13) { - e.preventDefault() - loadStructure('rcsb://' + value) - load2fofc(edmapUrl + value + '_2fofc.dsn6') - loadFofc(edmapUrl + value + '_fofc.dsn6') - } - } -}, { top: '350px', left: '12px', width: '120px' }) -addElement(loadEdmapInput) - -var isolevel2fofcText = createElement( - 'span', {}, { bottom: '32px', left: '12px', color: 'lightgrey' } -) -addElement(isolevel2fofcText) - -var isolevelFofcText = createElement( - 'span', {}, { bottom: '12px', left: '12px', color: 'lightgrey' } -) -addElement(isolevelFofcText) - -var fileStructureText = createElement('span', { - innerText: 'structure file: none' -}, { bottom: '52px', right: '12px', color: 'lightgrey' }) -addElement(fileStructureText) - -var file2fofcText = createElement('span', { - innerText: '2fofc file: none' -}, { bottom: '32px', right: '12px', color: 'lightgrey' }) -addElement(file2fofcText) - -var fileFofcText = createElement('span', { - innerText: 'fofc file: none' -}, { bottom: '12px', right: '12px', color: 'lightgrey' }) -addElement(fileFofcText) - -stage.mouseControls.add('scroll', function () { - if (surf2fofc) { - var level2fofc = surf2fofc.getParameters().isolevel.toFixed(1) - isolevel2fofcText.innerText = '2fofc level: ' + level2fofc + '\u03C3' - } - if (surfFofc) { - var levelFofc = surfFofc.getParameters().isolevel.toFixed(1) - isolevelFofcText.innerText = 'fofc level: ' + levelFofc + '\u03C3' - } -}) - -function loadExample (id) { - var pl - if (id === '3ek3') { - pl = [ - loadStructure('data://3ek3.cif'), - load2fofc('data://3ek3-2fofc.map.gz'), - loadFofc('data://3ek3-fofc.map.gz') - ] - } else if (id === '3nzd') { - pl = [ - loadStructure('data://3nzd.cif'), - load2fofc('data://3nzd.ccp4.gz'), - loadFofc('data://3nzd_diff.ccp4.gz') - ] - } else if (id === '1lee') { - pl = [ - loadStructure('data://1lee.pdb'), - load2fofc('data://1lee.ccp4'), - loadFofc('data://1lee_diff.ccp4') - ] - } - exampleSelect.value = '' - return Promise.all(pl) -} - -loadExample('3ek3') diff --git a/examples/examples/scripts/parser/brix.js b/examples/examples/scripts/parser/brix.js deleted file mode 100644 index 454f54240..000000000 --- a/examples/examples/scripts/parser/brix.js +++ /dev/null @@ -1,10 +0,0 @@ - -stage.loadFile('data://3str-2fofc.brix').then(function (o) { - o.addRepresentation('surface') - stage.autoView() -}) - -stage.loadFile('data://3str.cif').then(function (o) { - o.addRepresentation('licorice') - stage.autoView() -}) diff --git a/examples/examples/scripts/parser/ccp4.js b/examples/examples/scripts/parser/ccp4.js deleted file mode 100644 index 312d37cdf..000000000 --- a/examples/examples/scripts/parser/ccp4.js +++ /dev/null @@ -1,48 +0,0 @@ - -stage.loadFile('data://3pqr.ccp4.gz').then(function (o) { - o.addRepresentation('surface', { - contour: true, - color: 'skyblue', - boxSize: 10 - }) - o.autoView() - - var position = new NGL.Vector3() - function getCenterArray () { - position.copy(stage.viewerControls.position) - return position.negate().toArray() - } - - var sphereBuffer = new NGL.SphereBuffer( - { - position: new Float32Array(getCenterArray()), - color: new Float32Array([ 1, 0, 0 ]), - radius: new Float32Array([ 1 ]) - }, - { disableImpostor: true } - ) - o.addBufferRepresentation(sphereBuffer, { flatShaded: true }) - - stage.viewerControls.signals.changed.add(function () { - sphereBuffer.setAttributes({ - position: getCenterArray() - }) - }) -}) - -// mode 0 data -stage.loadFile('data://3pqr-mode0.ccp4').then(function (o) { - o.addRepresentation('surface', { - contour: true, - color: 'tomato', - boxSize: 10 - }) - o.autoView() -}) - -stage.loadFile('data://3pqr.pdb').then(function (o) { - o.addRepresentation('line', { - linewidth: 5, colorValue: 'yellow' - }) - o.autoView() -}) diff --git a/examples/examples/scripts/parser/cif-chemComp.js b/examples/examples/scripts/parser/cif-chemComp.js deleted file mode 100644 index 294d5524f..000000000 --- a/examples/examples/scripts/parser/cif-chemComp.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://PRDCC_000001.cif').then(function (o) { - o.addRepresentation('licorice', { sele: '/0', multipleBond: 'symmetric' }) - stage.autoView() -}) diff --git a/examples/examples/scripts/parser/cif-core.js b/examples/examples/scripts/parser/cif-core.js deleted file mode 100644 index 981edb32e..000000000 --- a/examples/examples/scripts/parser/cif-core.js +++ /dev/null @@ -1,14 +0,0 @@ - -stage.setParameters({ - cameraType: 'orthographic', - clipDist: 0 -}) - -stage.loadFile('data://Fe2O3_mp-715572_conventional_standard.cif').then(function (o) { - o.addRepresentation('licorice') - o.addRepresentation('spacefill', { - radiusScale: 0.25 - }) - o.addRepresentation('unitcell') - stage.autoView() -}) diff --git a/examples/examples/scripts/parser/cif.js b/examples/examples/scripts/parser/cif.js deleted file mode 100644 index 7044648c2..000000000 --- a/examples/examples/scripts/parser/cif.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://3SN6.cif').then(function (o) { - o.addRepresentation('cartoon', { radius: 'sstruc' }) - o.autoView() -}) diff --git a/examples/examples/scripts/parser/cns.js b/examples/examples/scripts/parser/cns.js deleted file mode 100644 index 38ea034f3..000000000 --- a/examples/examples/scripts/parser/cns.js +++ /dev/null @@ -1,12 +0,0 @@ - -stage.loadFile('data://3pqr.cns').then(function (o) { - o.addRepresentation('surface', { - visible: true, isolevel: 2.0, opacity: 0.6 - }) - // o.autoView(); -}) - -stage.loadFile('data://3pqr.pdb').then(function (o) { - o.addRepresentation('cartoon') - o.autoView() -}) diff --git a/examples/examples/scripts/parser/cube-benzene.js b/examples/examples/scripts/parser/cube-benzene.js deleted file mode 100644 index a69034aac..000000000 --- a/examples/examples/scripts/parser/cube-benzene.js +++ /dev/null @@ -1,25 +0,0 @@ - -stage.loadFile('data://benzene-homo.cube').then(function (o) { - o.addRepresentation('surface', { - visible: true, - isolevelType: 'value', - isolevel: 0.01, - color: 'blue', - opacity: 0.7, - opaqueBack: false - }) - o.addRepresentation('surface', { - visible: true, - isolevelType: 'value', - isolevel: -0.01, - color: 'red', - opacity: 0.7, - opaqueBack: false - }) - o.autoView() -}) - -stage.loadFile('data://benzene.sdf').then(function (o) { - o.addRepresentation('licorice') - o.autoView() -}) diff --git a/examples/examples/scripts/parser/cube-big.js b/examples/examples/scripts/parser/cube-big.js deleted file mode 100644 index 37f41bc1d..000000000 --- a/examples/examples/scripts/parser/cube-big.js +++ /dev/null @@ -1,21 +0,0 @@ - -Promise.all([ - stage.loadFile('data://rho-inactive_md-hydration.cube.gz'), - stage.loadFile('data://rho-inactive_md-system.gro') -]).then(function (oList) { - var o1 = oList[ 0 ] - var o2 = oList[ 1 ] - - o1.addRepresentation('surface', { isolevel: 2.7 }) - - o2.addRepresentation('cartoon') - o2.addRepresentation('licorice', { sele: 'hetero' }) - - var as = o2.structure.getAtomSetWithinVolume( - o1.volume, 2, o1.volume.getValueForSigma(2.7) - ) - var as2 = o2.structure.getAtomSetWithinGroup(as) - o2.addRepresentation('ball+stick', { sele: as2.toSeleString() }) - - stage.autoView() -}) diff --git a/examples/examples/scripts/parser/cube-bromobenzene.js b/examples/examples/scripts/parser/cube-bromobenzene.js deleted file mode 100644 index 5b4f23b51..000000000 --- a/examples/examples/scripts/parser/cube-bromobenzene.js +++ /dev/null @@ -1,10 +0,0 @@ - -stage.loadFile('data://bromobenzene-med.cube.gz').then(function (o) { - o.addRepresentation('surface', { opacity: 0.6 }) - stage.autoView() -}) - -stage.loadFile('data://bromobenzene.pdb').then(function (o) { - o.addRepresentation('ball+stick') - stage.autoView() -}) diff --git a/examples/examples/scripts/parser/cube-protein.js b/examples/examples/scripts/parser/cube-protein.js deleted file mode 100644 index 771760924..000000000 --- a/examples/examples/scripts/parser/cube-protein.js +++ /dev/null @@ -1,7 +0,0 @@ - -stage.loadFile('data://3ek3.cif', { defaultRepresentation: true }) - -stage.loadFile('data://3ek3-2fofc.cub').then(function (o) { - o.addRepresentation('surface', { opacity: 0.6 }) - o.autoView() -}) diff --git a/examples/examples/scripts/parser/cube.js b/examples/examples/scripts/parser/cube.js deleted file mode 100644 index ef0518560..000000000 --- a/examples/examples/scripts/parser/cube.js +++ /dev/null @@ -1,12 +0,0 @@ - -stage.loadFile('data://acrolein1gs.cube.gz').then(function (o) { - o.addRepresentation('surface', { - visible: true, isolevel: 0.1, opacity: 0.6 - }) - o.autoView() -}) - -stage.loadFile('data://acrolein.pdb').then(function (o) { - o.addRepresentation('licorice') - o.autoView() -}) diff --git a/examples/examples/scripts/parser/dcd-large.js b/examples/examples/scripts/parser/dcd-large.js deleted file mode 100644 index 367fbc1ad..000000000 --- a/examples/examples/scripts/parser/dcd-large.js +++ /dev/null @@ -1,20 +0,0 @@ - -stage.loadFile('data://md_1u19.gro').then(function (o) { - o.addRepresentation('cartoon') - o.addRepresentation('surface', { visible: false, lazy: true }) - o.autoView() - - NGL.autoLoad('data://md_1u19.dcd.gz').then(function (frames) { - o.addTrajectory(frames, { - initialFrame: 100, - defaultTimeout: 100, - defaultStep: undefined, - defaultInterpolateType: 'spline', - defaultDirection: 'forward', - centerPbc: false, - removePbc: false, - superpose: true, - sele: 'backbone and not hydrogen' - }) - }) -}) diff --git a/examples/examples/scripts/parser/dcd.js b/examples/examples/scripts/parser/dcd.js deleted file mode 100644 index 3ecf53eac..000000000 --- a/examples/examples/scripts/parser/dcd.js +++ /dev/null @@ -1,20 +0,0 @@ - -stage.loadFile('data://ala3.pdb').then(function (o) { - var atomPair = [ - // [ "1.CA", "3.CA" ] - [ 8, 28 ] - ] - - o.addRepresentation('licorice') - o.addRepresentation('cartoon', { sele: 'protein' }) - o.addRepresentation('distance', { - atomPair: atomPair, - labelColor: 'skyblue', - color: 'skyblue' - }) - o.autoView() - - NGL.autoLoad('data://ala3.dcd').then(function (frames) { - o.addTrajectory(frames) - }) -}) diff --git a/examples/examples/scripts/parser/dsn6.js b/examples/examples/scripts/parser/dsn6.js deleted file mode 100644 index 8b7f9eb97..000000000 --- a/examples/examples/scripts/parser/dsn6.js +++ /dev/null @@ -1,10 +0,0 @@ - -stage.loadFile('data://3str-2fofc.dsn6').then(function (o) { - o.addRepresentation('surface', { wireframe: true, color: 'tomato' }) - stage.autoView() -}) - -stage.loadFile('data://3str.cif').then(function (o) { - o.addRepresentation('licorice') - stage.autoView() -}) diff --git a/examples/examples/scripts/parser/dx.js b/examples/examples/scripts/parser/dx.js deleted file mode 100644 index add0941f2..000000000 --- a/examples/examples/scripts/parser/dx.js +++ /dev/null @@ -1,26 +0,0 @@ - -stage.loadFile('data://1crn_apbs_pot.dx.gz').then(function (o) { - o.addRepresentation('surface', { - isolevelType: 'value', - isolevel: -0.4, - smooth: 1, - color: 'red', - opacity: 0.6, - side: 'back', - useWorker: false, - opaqueBack: false - }) - - o.addRepresentation('surface', { - isolevelType: 'value', - isolevel: 0.4, - smooth: 1, - color: 'blue', - opacity: 0.6, - side: 'front', - useWorker: false, - opaqueBack: false - }) - - o.autoView() -}) diff --git a/examples/examples/scripts/parser/dxbin.js b/examples/examples/scripts/parser/dxbin.js deleted file mode 100644 index b0df7c7fd..000000000 --- a/examples/examples/scripts/parser/dxbin.js +++ /dev/null @@ -1,51 +0,0 @@ - -var promiseList = [ - stage.loadFile('data://3pqr.pqr'), - stage.loadFile('data://3pqr-pot.dxbin') -] - -Promise.all(promiseList).then(function (compList) { - var pqr = compList[ 0 ] - var dxbin = compList[ 1 ] - - pqr.addRepresentation('cartoon', { - colorScheme: 'bfactor', - colorScale: 'rwb', - colorDomain: [ -1, 0, 1 ] - }) - pqr.addRepresentation('licorice', { - colorScheme: 'bfactor', - colorScale: 'rwb', - colorDomain: [ -1, 0, 1 ] - }) - pqr.addRepresentation('surface', { - colorVolume: dxbin.volume, - colorScheme: 'volume', - colorScale: 'rwb', - colorDomain: [ -5, 0, 5 ] - }) - - pqr.autoView() - - dxbin.addRepresentation('surface', { - isolevelType: 'value', - isolevel: -1.5, - smooth: 1, - color: 'red', - opacity: 0.6, - side: 'back', - opaqueBack: false - }) - - dxbin.addRepresentation('surface', { - isolevelType: 'value', - isolevel: 1.5, - smooth: 1, - color: 'blue', - opacity: 0.6, - side: 'front', - opaqueBack: false - }) - - stage.autoView() -}) diff --git a/examples/examples/scripts/parser/gro-large.js b/examples/examples/scripts/parser/gro-large.js deleted file mode 100644 index 386ebaf04..000000000 --- a/examples/examples/scripts/parser/gro-large.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://water.gro').then(function (o) { - o.addRepresentation('line', { color: 'residueindex' }) - o.autoView() -}) diff --git a/examples/examples/scripts/parser/gro-trajectory.js b/examples/examples/scripts/parser/gro-trajectory.js deleted file mode 100644 index f630086db..000000000 --- a/examples/examples/scripts/parser/gro-trajectory.js +++ /dev/null @@ -1,13 +0,0 @@ - -stage.loadFile('data://md_1u19_trj.gro', { - asTrajectory: true, - sele: '50-100' -}).then(function (o) { - o.addTrajectory() - o.addRepresentation('cartoon') - o.addRepresentation('helixorient') - o.addRepresentation('line', { - sele: 'not hydrogen and sidechainAttached' - }) - stage.autoView() -}) diff --git a/examples/examples/scripts/parser/gro.js b/examples/examples/scripts/parser/gro.js deleted file mode 100644 index a59cef908..000000000 --- a/examples/examples/scripts/parser/gro.js +++ /dev/null @@ -1,6 +0,0 @@ - -stage.loadFile('data://md.gro').then(function (o) { - o.addRepresentation('cartoon') - o.addRepresentation('line') - o.autoView() -}) diff --git a/examples/examples/scripts/parser/kin.js b/examples/examples/scripts/parser/kin.js deleted file mode 100644 index d5c038528..000000000 --- a/examples/examples/scripts/parser/kin.js +++ /dev/null @@ -1,47 +0,0 @@ - -NGL.autoLoad('data://1crnFH-multi.kin').then(function (kinemage) { - for (let master in kinemage.masterDict) { - var shape = new NGL.Shape(master, { - pointSize: 3, - sizeAttenuation: false, - lineWidth: 3 - }) - - kinemage.dotLists.forEach(function (dotList) { - if (!dotList.masterArray.includes(master)) return - for (var i = 0, il = dotList.positionArray.length / 3; i < il; ++i) { - var i3 = i * 3 - var x = dotList.positionArray[ i3 ] - var y = dotList.positionArray[ i3 + 1 ] - var z = dotList.positionArray[ i3 + 2 ] - var r = dotList.colorArray[ i3 ] - var g = dotList.colorArray[ i3 + 1 ] - var b = dotList.colorArray[ i3 + 2 ] - shape.addPoint([ x, y, z ], [ r, g, b ], dotList.labelArray[ i ]) - } - }) - - kinemage.vectorLists.forEach(function (vectorList) { - if (!vectorList.masterArray.includes(master)) return - for (var i = 0, il = vectorList.position1Array.length / 3; i < il; ++i) { - var i3 = i * 3 - var x1 = vectorList.position1Array[ i3 ] - var y1 = vectorList.position1Array[ i3 + 1 ] - var z1 = vectorList.position1Array[ i3 + 2 ] - var x2 = vectorList.position2Array[ i3 ] - var y2 = vectorList.position2Array[ i3 + 1 ] - var z2 = vectorList.position2Array[ i3 + 2 ] - var r = vectorList.color1Array[ i3 ] - var g = vectorList.color1Array[ i3 + 1 ] - var b = vectorList.color1Array[ i3 + 2 ] - shape.addWideline([ x1, y1, z1 ], [ x2, y2, z2 ], [ r, g, b ], vectorList.label1Array[ i ]) - } - }) - - var visible = kinemage.masterDict[ master ].visible - var shapeComp = stage.addComponentFromObject(shape, { visible: visible }) - shapeComp.addRepresentation('buffer') - } - - stage.autoView() -}) diff --git a/examples/examples/scripts/parser/map.js b/examples/examples/scripts/parser/map.js deleted file mode 100644 index c6ef8d229..000000000 --- a/examples/examples/scripts/parser/map.js +++ /dev/null @@ -1,13 +0,0 @@ - -stage.loadFile('data://emd_2682.map.gz').then(function (o) { - o.addRepresentation('surface', { - opacity: 0.5, - opaqueBack: true - }) - stage.autoView() -}) - -stage.loadFile('data://4UJD.cif.gz').then(function (o) { - o.addRepresentation('cartoon', { color: 'chainindex' }) - stage.autoView() -}) diff --git a/examples/examples/scripts/parser/mmtf-reduced.js b/examples/examples/scripts/parser/mmtf-reduced.js deleted file mode 100644 index 5f03a3b6b..000000000 --- a/examples/examples/scripts/parser/mmtf-reduced.js +++ /dev/null @@ -1,2 +0,0 @@ - -stage.loadFile('data://1stp.bb.mmtf', { defaultRepresentation: true }) diff --git a/examples/examples/scripts/parser/mmtf.js b/examples/examples/scripts/parser/mmtf.js deleted file mode 100644 index 3a2854868..000000000 --- a/examples/examples/scripts/parser/mmtf.js +++ /dev/null @@ -1,6 +0,0 @@ - -stage.loadFile('data://1blu.mmtf').then(function (o) { - o.addRepresentation('cartoon', { color: 'residueindex' }) - o.addRepresentation('ball+stick', { sele: 'ligand' }) - o.autoView() -}) diff --git a/examples/examples/scripts/parser/mol2.js b/examples/examples/scripts/parser/mol2.js deleted file mode 100644 index 45fa10288..000000000 --- a/examples/examples/scripts/parser/mol2.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://adrenalin.mol2').then(function (o) { - o.addRepresentation('hyperball') - o.autoView() -}) diff --git a/examples/examples/scripts/parser/mrc.js b/examples/examples/scripts/parser/mrc.js deleted file mode 100644 index f8c08d377..000000000 --- a/examples/examples/scripts/parser/mrc.js +++ /dev/null @@ -1,2 +0,0 @@ - -stage.loadFile('data://betaGal.mrc', { defaultRepresentation: true }) diff --git a/examples/examples/scripts/parser/nctraj.js b/examples/examples/scripts/parser/nctraj.js deleted file mode 100644 index 8e8af4803..000000000 --- a/examples/examples/scripts/parser/nctraj.js +++ /dev/null @@ -1,9 +0,0 @@ - -stage.loadFile('data://DPDP.pdb').then(function (o) { - o.addRepresentation('licorice') - o.autoView() - - NGL.autoLoad('data://DPDP.nc').then(function (frames) { - o.addTrajectory(frames) - }) -}) diff --git a/examples/examples/scripts/parser/obj.js b/examples/examples/scripts/parser/obj.js deleted file mode 100644 index 97409eb43..000000000 --- a/examples/examples/scripts/parser/obj.js +++ /dev/null @@ -1,11 +0,0 @@ - -stage.loadFile('data://1crn.pdb').then(function (o) { - o.addRepresentation('spacefill') - o.autoView() -}) - -stage.loadFile('data://1crn.obj').then(function (o) { - o.addRepresentation('surface', { - opacity: 0.7, side: 'double' - }) -}) diff --git a/examples/examples/scripts/parser/pdb.js b/examples/examples/scripts/parser/pdb.js deleted file mode 100644 index 658f9012b..000000000 --- a/examples/examples/scripts/parser/pdb.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://1blu.pdb').then(function (o) { - o.addRepresentation('cartoon') - o.autoView() -}) diff --git a/examples/examples/scripts/parser/pdbqt.js b/examples/examples/scripts/parser/pdbqt.js deleted file mode 100644 index 3e79b499f..000000000 --- a/examples/examples/scripts/parser/pdbqt.js +++ /dev/null @@ -1,9 +0,0 @@ - -stage.loadFile('data://dxc.pdbqt', { - sele: '/0 or /1 or /2' -}).then(function (o) { - o.addRepresentation('licorice', { - colorScheme: 'partialCharge' - }) - stage.autoView() -}) diff --git a/examples/examples/scripts/parser/ply.js b/examples/examples/scripts/parser/ply.js deleted file mode 100644 index 53da45f57..000000000 --- a/examples/examples/scripts/parser/ply.js +++ /dev/null @@ -1,12 +0,0 @@ - -stage.loadFile('data://1crn.pdb').then(function (o) { - o.addRepresentation('cartoon') - o.addRepresentation('ball+stick') - o.autoView() -}) - -stage.loadFile('data://1crn.ply').then(function (o) { - o.addRepresentation('surface', { - opacity: 0.3, side: 'double' - }) -}) diff --git a/examples/examples/scripts/parser/pqr-explicit-radii.js b/examples/examples/scripts/parser/pqr-explicit-radii.js deleted file mode 100644 index 125cd739e..000000000 --- a/examples/examples/scripts/parser/pqr-explicit-radii.js +++ /dev/null @@ -1,16 +0,0 @@ - -stage.loadFile('data://1crn_apbs.pqr').then(function (o) { - o.addRepresentation('spacefill', { - radiusType: 'explicit', - colorScheme: 'partialCharge', - visible: false - }) - o.addRepresentation('surface', { - surfaceType: 'av', - colorScheme: 'electrostatic', - scaleFactor: 3.0, - opacity: 1.0, - radiusType: 'explicit' - }) - o.autoView() -}) diff --git a/examples/examples/scripts/parser/pqr.js b/examples/examples/scripts/parser/pqr.js deleted file mode 100644 index c1d2056c3..000000000 --- a/examples/examples/scripts/parser/pqr.js +++ /dev/null @@ -1,9 +0,0 @@ - -stage.loadFile('data://1crn_apbs.pqr').then(function (o) { - o.addRepresentation('cartoon') - o.addRepresentation('licorice', { - colorScheme: 'partialCharge', - colorScale: 'rwb' - }) - o.autoView() -}) diff --git a/examples/examples/scripts/parser/prmtop.js b/examples/examples/scripts/parser/prmtop.js deleted file mode 100644 index a852e83f1..000000000 --- a/examples/examples/scripts/parser/prmtop.js +++ /dev/null @@ -1,14 +0,0 @@ - -stage.loadFile('data://DPDP.prmtop').then(function (o) { - NGL.autoLoad('data://DPDP.nc').then(function (frames) { - o.addTrajectory(frames, { - initialFrame: 0, - deltaTime: 200 - }) - o.addRepresentation('licorice', {scale: 0.5}) - o.addRepresentation('spacefill', {sele: 'not :B'}) - o.addRepresentation('cartoon') - o.addRepresentation('backbone') - stage.autoView() - }) -}) diff --git a/examples/examples/scripts/parser/psf.js b/examples/examples/scripts/parser/psf.js deleted file mode 100644 index 54a2af0fb..000000000 --- a/examples/examples/scripts/parser/psf.js +++ /dev/null @@ -1,12 +0,0 @@ - -stage.loadFile('data://ala3.psf').then(function (o) { - NGL.autoLoad('data://ala3.dcd').then(function (frames) { - o.addTrajectory(frames, { - initialFrame: 0, - superpose: false - }) - o.addRepresentation('licorice', {scale: 0.5}) - o.addRepresentation('backbone') - stage.autoView() - }) -}) diff --git a/examples/examples/scripts/parser/sdf-models.js b/examples/examples/scripts/parser/sdf-models.js deleted file mode 100644 index 36a40744c..000000000 --- a/examples/examples/scripts/parser/sdf-models.js +++ /dev/null @@ -1,33 +0,0 @@ - -function addElement (el) { - Object.assign(el.style, { - position: 'absolute', - zIndex: 10 - }) - stage.viewer.container.appendChild(el) -} - -function createElement (name, properties, style) { - var el = document.createElement(name) - Object.assign(el, properties) - Object.assign(el.style, style) - return el -} - -stage.loadFile('data://ligands.sd').then(function (o) { - o.setSelection('/0') - o.addRepresentation('licorice') - o.autoView() - - var modelRange = createElement('input', { - type: 'range', - value: 0, - min: 0, - max: o.structure.modelStore.count - 1, - step: 1 - }, { top: '12px', left: '12px' }) - modelRange.oninput = function (e) { - o.setSelection('/' + e.target.value) - } - addElement(modelRange) -}) diff --git a/examples/examples/scripts/parser/sdf.js b/examples/examples/scripts/parser/sdf.js deleted file mode 100644 index 5263a19c7..000000000 --- a/examples/examples/scripts/parser/sdf.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://adrenalin.sdf').then(function (o) { - o.addRepresentation('hyperball') - o.autoView() -}) diff --git a/examples/examples/scripts/parser/top.js b/examples/examples/scripts/parser/top.js deleted file mode 100644 index a5181d05f..000000000 --- a/examples/examples/scripts/parser/top.js +++ /dev/null @@ -1,15 +0,0 @@ - -stage.loadFile('data://gpcr.top').then(function (o) { - NGL.autoLoad('data://gpcr.xtc').then(function (frames) { - o.addTrajectory(frames, { - initialFrame: 0, - centerPbc: true, - removePbc: true - }) - o.addRepresentation('cartoon') - o.addRepresentation('backbone') - o.addRepresentation('licorice', {sele: 'protein and not _h'}) - o.addRepresentation('line', {sele: 'popc and not _h'}) - stage.autoView() - }) -}) diff --git a/examples/examples/scripts/parser/trr.js b/examples/examples/scripts/parser/trr.js deleted file mode 100644 index 8a77b3948..000000000 --- a/examples/examples/scripts/parser/trr.js +++ /dev/null @@ -1,9 +0,0 @@ - -stage.loadFile('data://md.gro').then(function (o) { - o.addRepresentation('cartoon') - o.autoView() - - NGL.autoLoad('data://md.trr').then(function (frames) { - o.addTrajectory(frames) - }) -}) diff --git a/examples/examples/scripts/parser/validation.js b/examples/examples/scripts/parser/validation.js deleted file mode 100644 index c6365b176..000000000 --- a/examples/examples/scripts/parser/validation.js +++ /dev/null @@ -1,18 +0,0 @@ - -Promise.all([ - stage.loadFile('data://3PQR.cif'), - NGL.autoLoad('data://3pqr_validation.xml', { ext: 'validation' }) -]).then(function (ol) { - ol[ 0 ].structure.validation = ol[ 1 ] - ol[ 0 ].addRepresentation('cartoon', { color: 'geoquality' }) - ol[ 0 ].addRepresentation('validation') - ol[ 0 ].addRepresentation('ball+stick', { - sele: ol[ 1 ].clashSele, - color: 'geoquality' - }) - ol[ 0 ].addRepresentation('licorice', { - sele: 'hetero', - color: 'geoquality' - }) - stage.autoView() -}) diff --git a/examples/examples/scripts/parser/xtc.js b/examples/examples/scripts/parser/xtc.js deleted file mode 100644 index b47e88a49..000000000 --- a/examples/examples/scripts/parser/xtc.js +++ /dev/null @@ -1,9 +0,0 @@ - -stage.loadFile('data://md.gro').then(function (o) { - o.addRepresentation('cartoon') - o.autoView() - - NGL.autoLoad('data://md.xtc').then(function (frames) { - o.addTrajectory(frames) - }) -}) diff --git a/examples/examples/scripts/representation/angle.js b/examples/examples/scripts/representation/angle.js deleted file mode 100644 index 26f8ab075..000000000 --- a/examples/examples/scripts/representation/angle.js +++ /dev/null @@ -1,16 +0,0 @@ - -stage.loadFile('data://1blu.pdb').then(function (o) { - var atomTriple = [ - [ 2, 6, 9 ], - [ '2.CA', '2.C', '2.O' ] - ] - - o.addRepresentation('ball+stick', {sele: '1-2'}) - o.addRepresentation('angle', { - atomTriple: atomTriple, - labelSize: 1.0, - sdf: false - }) - - stage.autoView() -}) diff --git a/examples/examples/scripts/representation/axes.js b/examples/examples/scripts/representation/axes.js deleted file mode 100644 index 7ebba35d6..000000000 --- a/examples/examples/scripts/representation/axes.js +++ /dev/null @@ -1,16 +0,0 @@ - -stage.loadFile('rcsb://3pqr.mmtf', { - defaultAssembly: 'BU1' -}).then(function (o) { - o.addRepresentation('cartoon') - o.addRepresentation('axes', { - sele: 'RET', showAxes: false, showBox: true, radius: 0.2 - }) - o.addRepresentation('ball+stick', { sele: 'RET' }) - o.addRepresentation('axes', { - sele: ':B and backbone', showAxes: false, showBox: true, radius: 0.2 - }) - stage.autoView() - var pa = o.structure.getPrincipalAxes() - stage.animationControls.rotate(pa.getRotationQuaternion(), 1500) -}) diff --git a/examples/examples/scripts/representation/ball+stick.js b/examples/examples/scripts/representation/ball+stick.js deleted file mode 100644 index 5d86c3837..000000000 --- a/examples/examples/scripts/representation/ball+stick.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://1crn.pdb').then(function (o) { - o.addRepresentation('ball+stick') - o.autoView() -}) diff --git a/examples/examples/scripts/representation/contact.js b/examples/examples/scripts/representation/contact.js deleted file mode 100644 index 40c3ed600..000000000 --- a/examples/examples/scripts/representation/contact.js +++ /dev/null @@ -1,71 +0,0 @@ - -// create tooltip element and add to document body -var tooltip = document.createElement('div') -Object.assign(tooltip.style, { - display: 'none', - position: 'fixed', - zIndex: 10, - pointerEvents: 'none', - backgroundColor: 'rgba( 0, 0, 0, 0.6 )', - color: 'lightgrey', - padding: '8px', - fontFamily: 'sans-serif' -}) -document.body.appendChild(tooltip) - -// remove default hoverPick mouse action -stage.mouseControls.remove('hoverPick') - -// listen to `hovered` signal to move tooltip around and change its text -stage.signals.hovered.add(function (pickingProxy) { - if (pickingProxy) { - if (pickingProxy.atom || pickingProxy.bond) { - var atom = pickingProxy.atom || pickingProxy.closestBondAtom - var vm = atom.structure.data['@valenceModel'] - if (vm && vm.idealValence) { - tooltip.innerHTML = `${pickingProxy.getLabel()}
-
- Atom: ${atom.qualifiedName()}
- ideal valence: ${vm.idealValence[atom.index]}
- ideal geometry: ${vm.idealGeometry[atom.index]}
- implicit charge: ${vm.implicitCharge[atom.index]}
- formal charge: ${atom.formalCharge === null ? '?' : atom.formalCharge}
- ` - } else if (vm && vm.charge) { - tooltip.innerHTML = `${pickingProxy.getLabel()}
-
- Atom: ${atom.qualifiedName()}
- vm charge: ${vm.charge[atom.index]}
- vm implicitH: ${vm.implicitH[atom.index]}
- vm totalH: ${vm.totalH[atom.index]}
- vm geom: ${vm.idealGeometry[atom.index]}
- formal charge: ${atom.formalCharge === null ? '?' : atom.formalCharge}
- ` - } else { - tooltip.innerHTML = `${pickingProxy.getLabel()}` - } - } else { - tooltip.innerHTML = `${pickingProxy.getLabel()}` - } - var mp = pickingProxy.mouse.position - tooltip.style.bottom = window.innerHeight - mp.y + 3 + 'px' - tooltip.style.left = mp.x + 3 + 'px' - tooltip.style.display = 'block' - } else { - tooltip.style.display = 'none' - } -}) - -stage.loadFile('rcsb://1crn').then(function (o) { - o.addRepresentation('cartoon', { - colorScheme: 'sstruc' - }) - o.addRepresentation('contact', { - backboneHydrogenBond: true - }) - o.addRepresentation('licorice', { - multipleBond: 'symmetric', - sele: 'not water' - }) - stage.autoView() -}) diff --git a/examples/examples/scripts/representation/dihedral.js b/examples/examples/scripts/representation/dihedral.js deleted file mode 100644 index 85e8c5ed1..000000000 --- a/examples/examples/scripts/representation/dihedral.js +++ /dev/null @@ -1,21 +0,0 @@ - -stage.loadFile('data://1blu.pdb').then(function (o) { - var atomQuad = [ - [2, 5, 6, 9], - ['1.C', '1.N', '1.CA', '1.CB'], - ['3.CB', '3.CA', '3.N', '3.C'] - // ['1.N', '1.C', '1.CB', '1.CA'] - ] - - o.addRepresentation('ball+stick', {sele: '1-3'}) - o.addRepresentation('dihedral', { - atomQuad: atomQuad, - sdf: false, - labelSize: 1.0, - labelColor: 'skyblue', - colorValue: 'red', - sectorOpacity: 0.75 - }) - - o.autoView() -}) diff --git a/examples/examples/scripts/representation/distance.js b/examples/examples/scripts/representation/distance.js deleted file mode 100644 index 0a5c407f0..000000000 --- a/examples/examples/scripts/representation/distance.js +++ /dev/null @@ -1,16 +0,0 @@ - -stage.loadFile('data://1blu.pdb').then(function (o) { - var atomPair = [ - [ '1.CA', '10.CA' ], - [ 1, 209 ] - ] - - o.addRepresentation('cartoon') - o.addRepresentation('distance', { - atomPair: atomPair, - color: 'skyblue', - labelUnit: 'nm' - }) - - o.autoView() -}) diff --git a/examples/examples/scripts/representation/helixorient.js b/examples/examples/scripts/representation/helixorient.js deleted file mode 100644 index 1244c046e..000000000 --- a/examples/examples/scripts/representation/helixorient.js +++ /dev/null @@ -1,13 +0,0 @@ - -stage.loadFile('data://3dqb.pdb').then(function (o) { - // o.addRepresentation( "crossing", { - // ssBorder: true, radius: 0.6 - // } ); - // o.addRepresentation( "rope", { - // radius: 0.2 - // } ); - o.addRepresentation('cartoon') - o.addRepresentation('helixorient') - - o.autoView() -}) diff --git a/examples/examples/scripts/representation/hyperball.js b/examples/examples/scripts/representation/hyperball.js deleted file mode 100644 index c662287e1..000000000 --- a/examples/examples/scripts/representation/hyperball.js +++ /dev/null @@ -1,6 +0,0 @@ - -stage.loadFile('data://1crn.pdb').then(function (o) { - o.addRepresentation('cartoon') - o.addRepresentation('hyperball', { sele: 'sidechainAttached' }) - o.autoView() -}) diff --git a/examples/examples/scripts/representation/label.js b/examples/examples/scripts/representation/label.js deleted file mode 100644 index 206ef1396..000000000 --- a/examples/examples/scripts/representation/label.js +++ /dev/null @@ -1,19 +0,0 @@ - -stage.loadFile('data://1crn.pdb').then(function (o) { - o.addRepresentation('tube', { radius: 'sstruc' }) - o.addRepresentation('ball+stick', { sele: 'sidechainAttached' }) - o.addRepresentation('label', { - sele: '.CA', - color: 'element', - labelType: 'format', - labelFormat: '%(resname)s %(chainname)s%(resno)s' - }) - o.autoView() -}) - -stage.loadFile('data://1crn.ply').then(function (o) { - o.addRepresentation('surface', { - opacity: 0.3, - side: 'front' - }) -}) diff --git a/examples/examples/scripts/representation/licorice.js b/examples/examples/scripts/representation/licorice.js deleted file mode 100644 index 73af9bf43..000000000 --- a/examples/examples/scripts/representation/licorice.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://1crn.pdb').then(function (o) { - o.addRepresentation('licorice') - o.autoView() -}) diff --git a/examples/examples/scripts/representation/line-and-cross.js b/examples/examples/scripts/representation/line-and-cross.js deleted file mode 100644 index dd2d437b3..000000000 --- a/examples/examples/scripts/representation/line-and-cross.js +++ /dev/null @@ -1,8 +0,0 @@ -stage.loadFile('data://1blu.mmtf').then(function (o) { - o.addRepresentation('line', { - lines: true, - crosses: `lone`, - crossSize: 0.35 - }) - o.autoView() -}) diff --git a/examples/examples/scripts/representation/line.js b/examples/examples/scripts/representation/line.js deleted file mode 100644 index 05940cd18..000000000 --- a/examples/examples/scripts/representation/line.js +++ /dev/null @@ -1,16 +0,0 @@ - -stage.loadFile('data://1crn.pdb').then(function (o) { - o.addRepresentation('ribbon') - o.addRepresentation('line', { - sele: 'sidechainAttached', - linewidth: 7 - }) - o.addRepresentation('point', { - sele: 'sidechainAttached', - sizeAttenuation: false, - pointSize: 7, - alphaTest: 1, - useTexture: true - }) - o.autoView() -}) diff --git a/examples/examples/scripts/representation/molecularsurface-av.js b/examples/examples/scripts/representation/molecularsurface-av.js deleted file mode 100644 index df3011eca..000000000 --- a/examples/examples/scripts/representation/molecularsurface-av.js +++ /dev/null @@ -1,31 +0,0 @@ - -stage.loadFile('data://2vts.mmtf').then(function (o) { - o.addRepresentation('line', { sele: 'not hetero' }) - o.addRepresentation('licorice', { - multipleBond: 'symmetric', - sele: 'hetero and (not water)' - }) - o.addRepresentation('surface', { - sele: 'hetero and (not water)', - surfaceType: 'av', - contour: true, - colorScheme: 'element', - colorValue: '#0f0', - useWorker: false - }) - o.addRepresentation('surface', { - sele: 'not hetero', - surfaceType: 'av', - colorScheme: 'bfactor', - contour: true, - filterSele: '10 OR 11 OR 12 OR 13 OR 14 OR 18 OR 31 OR 33 OR ' + - '64 OR 80 OR 81 OR 82 OR 83 OR 84 OR 85 OR 86 OR ' + - '129 OR 131 OR 132 OR 134 OR 144 OR 145' - }) - stage.viewerControls.orient([ - -25.08, 20.9, -12.01, 0, - 3.52, -13.97, -31.66, 0, - -23.85, -24.05, 7.95, 0, - -27.16, -8.65, -63.38, 1 - ]) -}) diff --git a/examples/examples/scripts/representation/molecularsurface-filter.js b/examples/examples/scripts/representation/molecularsurface-filter.js deleted file mode 100644 index 067c5b510..000000000 --- a/examples/examples/scripts/representation/molecularsurface-filter.js +++ /dev/null @@ -1,43 +0,0 @@ - -// stage.loadFile( "data://3pqr.pdb" ).then( function( o ){ -// stage.loadFile( "rcsb://4cup" ).then( function( o ){ -stage.loadFile('rcsb://4hhb').then(function (o) { - // var ligSele = "RET"; - // var ligSele = "ZYB"; - var ligSele = 'HEM and :B' - var sview = o.structure.getView(new NGL.Selection(ligSele)) - var filterSet = o.structure.getAtomSetWithinSelection(new NGL.Selection(ligSele), 7) - var filterSet2 = o.structure.getAtomSetWithinSelection(new NGL.Selection(ligSele), 5) - var groupSet = o.structure.getAtomSetWithinGroup(filterSet2) - - o.addRepresentation('licorice', { - sele: groupSet.toSeleString() - }) - o.addRepresentation('ball+stick', { - sele: ligSele - }) - - o.addRepresentation('surface', { - sele: 'polymer', - surfaceType: 'ms', - colorScheme: 'uniform', - opacity: 0.7, - opaqueBack: false, - useWorker: false, - clipCenter: sview.center, - filterSele: filterSet.toSeleString() - // filterSele: groupSet.toSeleString() - }) - - o.addRepresentation('surface', { - sele: 'polymer', - surfaceType: 'ms', - color: 'lime', - opacity: 0.7, - wireframe: true, - clipRadius: sview.boundingBox.getSize(new NGL.Vector3()).length() / 2 + 5, - clipCenter: sview.center - }) - - stage.autoView() -}) diff --git a/examples/examples/scripts/representation/molecularsurface.js b/examples/examples/scripts/representation/molecularsurface.js deleted file mode 100644 index 14e3b1a10..000000000 --- a/examples/examples/scripts/representation/molecularsurface.js +++ /dev/null @@ -1,14 +0,0 @@ - -stage.loadFile('data://1crn.pdb').then(function (o) { - o.addRepresentation('surface', { - surfaceType: 'ms', - smooth: 2, - probeRadius: 1.4, - scaleFactor: 2.0, - flatShaded: false, - opacity: 0.7, - lowResolution: false, - colorScheme: 'element' - }) - o.autoView() -}) diff --git a/examples/examples/scripts/representation/point.js b/examples/examples/scripts/representation/point.js deleted file mode 100644 index 8fe4ca5e9..000000000 --- a/examples/examples/scripts/representation/point.js +++ /dev/null @@ -1,16 +0,0 @@ - -stage.loadFile('data://1crn.pdb').then(function (o) { - o.addRepresentation('licorice') - o.addRepresentation('point', { - sele: '*', - sizeAttenuation: true, - pointSize: 7, - opacity: 0.6, - useTexture: true, - alphaTest: 0.0, - edgeBleach: 1.0, - forceTransparent: true, - sortParticles: true - }) - o.autoView() -}) diff --git a/examples/examples/scripts/representation/representation-lazy.js b/examples/examples/scripts/representation/representation-lazy.js deleted file mode 100644 index 712deb051..000000000 --- a/examples/examples/scripts/representation/representation-lazy.js +++ /dev/null @@ -1,6 +0,0 @@ - -stage.loadFile('rcsb://3pqr.mmtf').then(function (o) { - o.addRepresentation('cartoon') - o.addRepresentation('surface', { visible: false, lazy: true }) - stage.autoView() -}) diff --git a/examples/examples/scripts/representation/rocket.js b/examples/examples/scripts/representation/rocket.js deleted file mode 100644 index fca7beca4..000000000 --- a/examples/examples/scripts/representation/rocket.js +++ /dev/null @@ -1,6 +0,0 @@ - -stage.loadFile('data://1crn.pdb').then(function (o) { - o.addRepresentation('cartoon') - o.addRepresentation('rocket') - o.autoView() -}) diff --git a/examples/examples/scripts/representation/slice.js b/examples/examples/scripts/representation/slice.js deleted file mode 100644 index 255d93a91..000000000 --- a/examples/examples/scripts/representation/slice.js +++ /dev/null @@ -1,19 +0,0 @@ - -Promise.all([ - stage.loadFile('data://3pqr.ccp4.gz'), - stage.loadFile('data://3pqr.pdb') -]).then(function (ol) { - var sele = new NGL.Selection('245:A.NZ') - - ol[ 0 ].addRepresentation('slice', { - dimension: 'z', - positionType: 'coordinate', - position: ol[ 1 ].structure.getView(sele).center.z - }) - ol[ 0 ].addRepresentation('surface') - - ol[ 1 ].addRepresentation('licorice') - ol[ 1 ].addRepresentation('cartoon') - - stage.autoView() -}) diff --git a/examples/examples/scripts/representation/spacefill.js b/examples/examples/scripts/representation/spacefill.js deleted file mode 100644 index 3513c2fb1..000000000 --- a/examples/examples/scripts/representation/spacefill.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://1crn.pdb').then(function (o) { - o.addRepresentation('spacefill') - o.autoView() -}) diff --git a/examples/examples/scripts/representation/trace.js b/examples/examples/scripts/representation/trace.js deleted file mode 100644 index 1c53c5ed0..000000000 --- a/examples/examples/scripts/representation/trace.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://1crn.pdb').then(function (o) { - o.addRepresentation('trace') - o.autoView() -}) diff --git a/examples/examples/scripts/representation/tube-bfactor.js b/examples/examples/scripts/representation/tube-bfactor.js deleted file mode 100644 index 072dabfc9..000000000 --- a/examples/examples/scripts/representation/tube-bfactor.js +++ /dev/null @@ -1,19 +0,0 @@ - -stage.loadFile('data://1u19.pdb').then(function (o) { - o.addRepresentation('tube', { - sele: ':A', - radiusType: 'bfactor', - radiusScale: 0.010, - color: 'bfactor', - colorScale: 'RdYlBu' - }) - - o.addRepresentation('ball+stick', { - sele: ':A and sidechainAttached', - aspectRatio: 1.5, - color: 'bfactor', - colorScale: 'RdYlBu' - }) - - o.autoView(':A') -}) diff --git a/examples/examples/scripts/representation/unitcell.js b/examples/examples/scripts/representation/unitcell.js deleted file mode 100644 index 7b64d8aef..000000000 --- a/examples/examples/scripts/representation/unitcell.js +++ /dev/null @@ -1,9 +0,0 @@ - -stage.loadFile('data://3pqr.pdb').then(function (o) { - o.addRepresentation('cartoon') - o.addRepresentation('unitcell') - o.addRepresentation('ribbon', { - assembly: 'UNITCELL', color: 0x00DD11, scale: 0.9 - }) - stage.autoView() -}) diff --git a/examples/examples/scripts/selection/aromatic.js b/examples/examples/scripts/selection/aromatic.js deleted file mode 100644 index 6265e9477..000000000 --- a/examples/examples/scripts/selection/aromatic.js +++ /dev/null @@ -1,8 +0,0 @@ - -stage.loadFile('data://3pqr.pdb').then(function (o) { - o.addRepresentation('line') - o.addRepresentation('licorice', { radius: 0.3, sele: 'ring' }) - o.addRepresentation('spacefill', { radius: 0.5, sele: 'aromaticRing' }) - - stage.autoView() -}) diff --git a/examples/examples/scripts/selection/basic.js b/examples/examples/scripts/selection/basic.js deleted file mode 100644 index 0edeee489..000000000 --- a/examples/examples/scripts/selection/basic.js +++ /dev/null @@ -1,8 +0,0 @@ - -stage.loadFile('data://1crn.pdb').then(function (o) { - var sele = 'not backbone or .CA or (PRO and .N)' - - o.addRepresentation('cartoon') - o.addRepresentation('licorice', { sele: sele }) - o.autoView() -}) diff --git a/examples/examples/scripts/selection/bonded.js b/examples/examples/scripts/selection/bonded.js deleted file mode 100644 index 230833cd9..000000000 --- a/examples/examples/scripts/selection/bonded.js +++ /dev/null @@ -1,12 +0,0 @@ - -stage.loadFile('data://1blu.mmtf').then(function (o) { - o.addRepresentation('cartoon') - - o.addRepresentation('ball+stick') - - o.addRepresentation('spacefill', { - sele: 'not bonded', opacity: 0.6 - }) - - stage.autoView() -}) diff --git a/examples/examples/scripts/selection/component.js b/examples/examples/scripts/selection/component.js deleted file mode 100644 index 94698c22b..000000000 --- a/examples/examples/scripts/selection/component.js +++ /dev/null @@ -1,14 +0,0 @@ - -stage.loadFile('data://3pqr.pdb').then(function (o) { - o.addRepresentation('trace', {}, true) - var cartoon = o.addRepresentation('cartoon', {}, true) - var licorice = o.addRepresentation('spacefill', { - color: 'element', sele: 'TYR' - }, true) - - o.autoView() - - o.setSelection('1-90') - cartoon.setSelection('4-50') - licorice.setSelection('PRO') -}) diff --git a/examples/examples/scripts/selection/large.js b/examples/examples/scripts/selection/large.js deleted file mode 100644 index ec172a467..000000000 --- a/examples/examples/scripts/selection/large.js +++ /dev/null @@ -1,27 +0,0 @@ - -// Add new color scheme byElement -var flatSyntax = '( 339:O/0 OR 76:O/0 OR 278:H/0 OR 143:H/0 OR 335:M/0 OR 196:M/0 OR 669:N/0 OR 389:N/0 OR 112:L/0 OR 192:M/0 OR 267:M/0 OR 104:C/0 OR 225:B/0 OR 225:b/0 OR 155:c/0 OR 237:O/0 OR 44:I/0 OR 175:I/0 OR 30:N/0 OR 315:N/0 OR 327:O/0 OR 139:I/0 OR 187:I/0 OR 141:T/0 OR 53:T/0 OR 39:M/0 OR 335:M/0 OR 81:X/0 OR 785:N/0 OR 5:I/0 OR 195:C/0 OR 96:C/0 OR 214:c/0 OR 117:c/0 OR 249:J/0 OR 133:M/0 OR 124:M/0 OR 138:Q/0 OR 77:Q/0 OR 404:Q/0 OR 144:Q/0 OR 110:H/0 OR 204:J/0 OR 109:E/0 OR 49:H/0 OR 48:e/0 OR 31:K/0 OR 15:J/0 OR 99:V/0 OR 154:V/0 OR 32:A/0 OR 109:A/0 OR 17:a/0 OR 120:a/0 OR 278:K/0 OR 40:L/0 OR 59:l/0 OR 27:l/0 OR 71:7/0 OR 112:7/0 OR 638:N/0 OR 269:N/0 OR 339:R/0 OR 34:R/0 OR 274:N/0 OR 175:J/0 OR 145:M/0 OR 70:L/0 OR 66:K/0 OR 6:M/0 OR 140:Q/0 OR 101:A/0 OR 81:h/0 OR 101:3/0 OR 131:a/0 OR 43:X/0 OR 44:N/0 OR 82:V/0 OR 43:V/0 OR 524:Z/0 OR 171:O/0 OR 383:R/0 OR 248:R/0 OR 49:H/0 OR 52:J/0 OR 181:D/0 OR 202:D/0 OR 130:d/0 OR 73:d/0 OR 113:Q/0 OR 166:A/0 OR 221:A/0 OR 59:a/0 OR 177:a/0 OR 321:H/0 OR 257:L/0 OR 197:L/0 OR 255:J/0 OR 86:J/0 OR 329:K/0 OR 27:I/0 OR 188:V/0 OR 56:U/0 OR 401:Q/0 OR 136:Q/0 OR 317:L/0 OR 199:J/0 OR 127:J/0 OR 356:M/0 OR 404:P/0 OR 33:k/0 OR 80:j/0 OR 90:5/0 OR 30:6/0 OR 12:U/0 OR 174:k/0 OR 92:6/0 OR 162:M/0 OR 328:M/0 OR 346:K/0 OR 148:C/0 OR 99:C/0 OR 61:c/0 OR 44:c/0 OR 162:J/0 OR 85:A/0 OR 68:a/0 OR 329:H/0 OR 101:L/0 OR 136:N/0 OR 666:N/0 OR 69:k/0 OR 72:k/0 OR 85:6/0 OR 181:6/0 OR 73:K/0 OR 34:O/0 OR 354:O/0 OR 235:K/0 OR 52:V/0 OR 276:K/0 OR 113:K/0 OR 345:R/0 OR 364:R/0 OR 79:L/0 OR 48:U/0 OR 302:J/0 OR 252:S/0 OR 355:R/0 OR 138:U/0 OR 313:M/0 OR 108:L/0 OR 105:B/0 OR 110:B/0 OR 121:b/0 OR 30:b/0 OR 28:K/0 OR 227:K/0 OR 159:N/0 OR 194:S/0 OR 8:L/0 OR 70:O/0 OR 106:P/0 OR 29:K/0 OR 358:R/0 OR 354:J/0 OR 219:P/0 OR 112:P/0 OR 720:N/0 OR 490:N/0 OR 261:T/0 OR 182:T/0 OR 103:C/0 OR 83:j/0 OR 131:5/0 OR 228:c/0 OR 207:N/0 OR 274:J/0 OR 24:A/0 OR 110:B/0 OR 116:b/0 OR 44:a/0 OR 130:O/0 OR 16:U/0 OR 11:O/0 OR 280:O/0 OR 116:O/0 OR 23:K/0 OR 17:H/0 OR 72:H/0 OR 432:Z/0 OR 30:Z/0 OR 132:O/0 OR 46:Q/0 OR 131:C/0 OR 207:c/0 OR 355:Q/0 OR 106:Q/0 OR 177:2/0 OR 191:2/0 OR 78:9/0 OR 3:9/0 OR 176:V/0 OR 131:W/0 OR 219:V/0 OR 249:R/0 OR 129:U/0 OR 365:O/0 OR 157:F/0 OR 209:F/0 OR 75:f/0 OR 62:f/0 OR 97:M/0 OR 280:L/0 OR 371:R/0 OR 430:Q/0 OR 211:O/0 OR 364:P/0 OR 233:K/0 OR 357:P/0 OR 37:Q/0 OR 34:U/0 OR 25:P/0 OR 18:J/0 OR 77:J/0 OR 20:L/0 OR 56:S/0 OR 244:S/0 OR 331:S/0 OR 141:A/0 OR 35:a/0 OR 3:J/0 OR 191:D/0 OR 228:D/0 OR 62:d/0 OR 133:d/0 OR 75:H/0 OR 21:N/0 OR 130:S/0 OR 688:N/0 OR 59:J/0 OR 24:H/0 OR 137:F/0 OR 136:F/0 OR 216:f/0 OR 82:f/0 OR 376:P/0 OR 219:P/0 OR 660:N/0 OR 197:W/0 OR 254:U/0 OR 280:R/0 OR 239:T/0 OR 263:S/0 OR 123:X/0 OR 281:I/0 OR 1:X/0 OR 402:N/0 OR 428:N/0 OR 6:N/0 OR 449:Z/0 OR 19:M/0 OR 270:L/0 OR 66:M/0 OR 180:P/0 OR 226:B/0 OR 57:b/0 OR 82:K/0 OR 64:A/0 OR 146:a/0 OR 193:O/0 OR 144:L/0 OR 181:O/0 OR 161:P/0 OR 298:P/0 OR 451:Z/0 OR 295:Z/0 OR 206:E/0 OR 75:e/0 OR 227:S/0 OR 16:O/0 OR 285:O/0 OR 160:U/0 OR 387:R/0 OR 39:O/0 OR 155:O/0 OR 315:O/0 OR 238:L/0 OR 8:K/0 OR 278:J/0 OR 326:M/0 OR 24:I/0 OR 530:N/0 OR 49:N/0 OR 97:I/0 OR 126:H/0 OR 338:J/0 OR 155:G/0 OR 243:A/0 OR 170:a/0 OR 135:g/0 OR 248:S/0 OR 391:R/0 OR 54:O/0 OR 23:O/0 OR 124:Z/0 OR 210:E/0 OR 20:E/0 OR 110:e/0 OR 120:e/0 OR 230:A/0 OR 59:a/0 OR 5:H/0 OR 148:1/0 OR 81:2/0 OR 127:9/0 OR 199:8/0 OR 164:Q/0 OR 95:U/0 OR 114:U/0 OR 46:N/0 OR 45:X/0 OR 56:B/0 OR 96:b/0 OR 25:D/0 OR 151:d/0 OR 282:R/0 OR 1:M/0 OR 188:U/0 OR 148:I/0 OR 79:P/0 OR 716:N/0 OR 269:K/0 OR 86:R/0 OR 101:1/0 OR 66:1/0 OR 163:8/0 OR 101:8/0 OR 210:J/0 OR 322:O/0 OR 118:U/0 OR 660:Z/0 OR 637:Z/0 OR 740:Z/0 OR 154:L/0 OR 231:U/0 OR 134:U/0 OR 333:K/0 OR 374:Q/0 OR 270:Q/0 OR 135:Q/0 OR 213:U/0 OR 53:J/0 OR 337:S/0 OR 186:1/0 OR 48:8/0 OR 243:L/0 OR 67:D/0 OR 170:d/0 OR 105:J/0 OR 190:O/0 OR 160:K/0 OR 303:K/0 OR 165:L/0 OR 166:J/0 OR 17:X/0 OR 342:S/0 OR 161:k/0 OR 109:6/0 OR 224:J/0 OR 50:Q/0 OR 134:J/0 OR 205:I/0 OR 74:I/0 OR 225:E/0 OR 49:e/0 OR 121:G/0 OR 225:g/0 OR 152:L/0 OR 363:R/0 OR 159:R/0 OR 323:K/0 OR 278:L/0 OR 326:J/0 OR 53:N/0 OR 141:D/0 OR 158:d/0 OR 254:I/0 OR 374:O/0 OR 250:O/0 OR 205:U/0 OR 28:1/0 OR 170:i/0 OR 25:4/0 OR 116:8/0 OR 376:N/0 OR 81:1/0 OR 95:l/0 OR 94:7/0 OR 208:8/0 OR 280:H/0 OR 125:K/0 OR 22:E/0 OR 33:E/0 OR 134:e/0 OR 148:e/0 OR 302:P/0 OR 79:U/0 OR 232:P/0 OR 343:P/0 OR 206:I/0 OR 261:R/0 OR 107:P/0 OR 255:L/0 OR 83:W/0 OR 154:J/0 OR 169:R/0 OR 20:R/0 OR 712:N/0 OR 61:M/0 OR 102:G/0 OR 80:g/0 OR 170:W/0 OR 181:J/0 OR 403:S/0 OR 236:L/0 OR 154:H/0 OR 364:P/0 OR 2:K/0 OR 212:O/0 OR 42:U/0 OR 240:J/0 OR 334:O/0 OR 164:O/0 OR 31:1/0 OR 209:8/0 OR 219:N/0 OR 353:S/0 OR 30:S/0 OR 204:D/0 OR 111:d/0 OR 808:N/0 OR 331:N/0 OR 232:U/0 OR 250:P/0 OR 179:D/0 OR 18:I/0 OR 45:d/0 OR 164:M/0 OR 21:H/0 OR 183:B/0 OR 148:b/0 OR 323:K/0 OR 317:O/0 OR 53:M/0 OR 7:M/0 OR 113:J/0 OR 34:C/0 OR 56:c/0 OR 345:H/0 OR 685:N/0 OR 51:S/0 OR 185:W/0 OR 33:F/0 OR 125:f/0 OR 56:I/0 OR 106:P/0 OR 210:T/0 OR 55:T/0 OR 149:H/0 OR 93:W/0 OR 355:S/0 OR 36:U/0 OR 146:O/0 OR 705:N/0 OR 214:T/0 OR 85:S/0 OR 309:I/0 OR 177:M/0 OR 380:N/0 OR 57:X/0 OR 34:V/0 OR 142:1/0 OR 19:8/0 OR 674:N/0 OR 19:K/0 OR 141:k/0 OR 150:6/0 OR 39:O/0 OR 120:k/0 OR 183:k/0 OR 178:6/0 OR 25:6/0 OR 311:Q/0 OR 147:Q/0 OR 52:L/0 OR 96:C/0 OR 41:C/0 OR 179:c/0 OR 49:c/0 OR 115:T/0 OR 284:S/0 OR 133:i/0 OR 83:2/0 OR 109:9/0 OR 197:4/0 OR 70:V/0 OR 33:J/0 OR 100:C/0 OR 69:c/0 OR 191:P/0 OR 99:V/0 OR 92:Q/0 OR 203:L/0 OR 13:J/0 OR 55:H/0 OR 155:2/0 OR 159:9/0 OR 236:G/0 OR 49:g/0 OR 71:N/0 OR 52:G/0 OR 138:g/0 OR 230:T/0 OR 40:T/0 OR 332:K/0 OR 168:U/0 OR 131:L/0 OR 128:D/0 OR 70:d/0 OR 161:J/0 OR 232:H/0 OR 168:A/0 OR 180:a/0 OR 34:O/0 OR 66:2/0 OR 204:9/0 OR 408:P/0 OR 317:L/0 OR 334:L/0 OR 244:N/0 OR 272:M/0 OR 334:N/0 OR 95:P/0 OR 156:I/0 OR 138:E/0 OR 20:e/0 OR 123:H/0 OR 85:M/0 OR 219:Q/0 OR 41:H/0 OR 389:Q/0 OR 288:Q/0 OR 53:1/0 OR 179:8/0 OR 258:Q/0 OR 252:Q/0 OR 416:Z/0 OR 125:Q/0 OR 259:L/0 OR 120:J/0 OR 175:I/0 OR 202:1/0 OR 65:l/0 OR 46:7/0 OR 67:8/0 OR 213:E/0 OR 45:E/0 OR 56:e/0 OR 232:e/0 OR 550:Z/0 OR 398:Q/0 OR 208:N/0 OR 94:H/0 OR 400:N/0 OR 334:L/0 OR 133:K/0 OR 86:U/0 OR 121:R/0 OR 192:R/0 OR 259:S/0 OR 305:L/0 OR 104:2/0 OR 161:9/0 OR 292:P/0 OR 369:P/0 OR 133:R/0 OR 418:S/0 OR 373:J/0 OR 125:O/0 OR 363:R/0 OR 157:L/0 OR 59:j/0 OR 74:5/0 OR 135:T/0 OR 70:M/0 OR 65:L/0 OR 193:H/0 OR 290:P/0 OR 331:P/0 OR 372:Q/0 OR 293:K/0 OR 175:h/0 OR 98:3/0 OR 117:R/0 OR 317:I/0 OR 214:C/0 OR 60:c/0 OR 9:T/0 OR 244:V/0 OR 196:V/0 OR 253:N/0 OR 270:R/0 OR 227:T/0 OR 40:T/0 OR 102:k/0 OR 76:6/0 OR 4:D/0 OR 149:I/0 OR 172:d/0 OR 97:D/0 OR 210:d/0 OR 109:T/0 OR 218:T/0 OR 282:Q/0 OR 3:2/0 OR 199:F/0 OR 18:f/0 OR 4:9/0 OR 375:Q/0 OR 42:A/0 OR 232:C/0 OR 64:c/0 OR 14:a/0 OR 165:P/0 OR 428:S/0 OR 722:Z/0 OR 123:F/0 OR 216:f/0 OR 123:G/0 OR 195:G/0 OR 1:g/0 OR 114:g/0 OR 179:i/0 OR 202:4/0 OR 118:V/0 OR 357:K/0 OR 55:I/0 OR 542:Z/0 OR 103:W/0 OR 94:Q/0 OR 109:U/0 OR 295:M/0 OR 295:L/0 OR 219:K/0 OR 270:M/0 OR 256:M/0 OR 226:U/0 OR 39:k/0 OR 167:6/0 OR 448:N/0 OR 401:S/0 OR 251:M/0 OR 38:M/0 OR 78:Q/0 OR 111:Q/0 OR 35:1/0 OR 61:1/0 OR 177:8/0 OR 122:8/0 OR 102:N/0 OR 240:S/0 OR 357:R/0 OR 126:V/0 OR 90:U/0 OR 59:I/0 OR 139:S/0 OR 269:S/0 OR 101:J/0 OR 9:j/0 OR 203:5/0 OR 327:M/0 OR 6:U/0 OR 116:P/0 OR 95:S/0 OR 210:O/0 OR 13:N/0 OR 4:X/0 OR 655:Z/0 OR 181:S/0 OR 280:Q/0 OR 49:G/0 OR 218:T/0 OR 94:g/0 OR 69:D/0 OR 109:D/0 OR 194:d/0 OR 124:d/0 OR 145:G/0 OR 65:g/0 OR 29:O/0 OR 90:B/0 OR 181:b/0 OR 137:N/0 OR 635:Z/0 OR 65:k/0 OR 155:6/0 OR 112:j/0 OR 128:l/0 OR 59:7/0 OR 57:5/0 OR 299:Q/0 OR 275:Q/0 OR 211:F/0 OR 171:F/0 OR 117:f/0 OR 4:f/0 OR 55:1/0 OR 55:8/0 OR 88:K/0 OR 153:U/0 OR 35:U/0 OR 211:P/0 OR 221:H/0 OR 5:L/0 OR 156:V/0 OR 204:V/0 OR 99:L/0 OR 45:U/0 OR 105:T/0 OR 17:C/0 OR 35:c/0 OR 248:I/0 OR 199:S/0 OR 295:R/0 OR 71:V/0 OR 118:S/0 OR 44:C/0 OR 120:c/0 OR 197:O/0 OR 115:Q/0 OR 111:H/0 OR 510:Z/0 OR 91:l/0 OR 81:7/0 OR 86:O/0 OR 124:E/0 OR 45:e/0 OR 145:F/0 OR 132:f/0 OR 90:S/0 OR 388:S/0 OR 577:N/0 OR 485:N/0 OR 62:N/0 OR 425:Q/0 OR 85:D/0 OR 72:d/0 OR 275:P/0 OR 110:B/0 OR 211:b/0 OR 370:N/0 OR 28:I/0 OR 341:R/0 OR 279:L/0 OR 82:V/0 OR 37:Q/0 OR 44:B/0 OR 197:b/0 OR 229:J/0 OR 120:U/0 OR 249:T/0 OR 233:T/0 OR 160:B/0 OR 82:b/0 OR 88:V/0 OR 199:P/0 OR 734:N/0 OR 82:E/0 OR 158:e/0 OR 153:A/0 OR 136:a/0 OR 59:J/0 OR 63:L/0 OR 11:Q/0 OR 7:S/0 OR 76:1/0 OR 14:V/0 OR 49:8/0 OR 7:P/0 OR 156:R/0 OR 548:N/0 OR 140:N/0 OR 124:R/0 OR 429:Q/0 OR 246:Q/0 OR 13:W/0 OR 79:H/0 OR 171:S/0 OR 158:1/0 OR 217:8/0 OR 519:N/0 OR 104:Q/0 OR 353:Z/0 OR 538:Z/0 OR 199:T/0 OR 86:V/0 OR 586:Z/0 OR 27:W/0 OR 103:O/0 OR 377:Q/0 OR 77:N/0 OR 328:N/0 OR 197:T/0 OR 318:N/0 OR 205:L/0 OR 267:P/0 OR 271:H/0 OR 20:H/0 OR 223:I/0 OR 37:D/0 OR 195:d/0 OR 315:Z/0 OR 158:V/0 OR 630:N/0 OR 140:G/0 OR 171:g/0 OR 210:I/0 OR 69:R/0 OR 323:I/0 OR 20:E/0 OR 74:E/0 OR 134:e/0 OR 53:e/0 OR 90:Q/0 OR 226:U/0 OR 222:E/0 OR 69:e/0 OR 121:D/0 OR 222:d/0 OR 217:E/0 OR 222:e/0 OR 267:Q/0 OR 359:Z/0 OR 87:k/0 OR 112:6/0 OR 58:N/0 OR 70:S/0 OR 280:K/0 OR 70:M/0 OR 349:R/0 OR 53:D/0 OR 12:d/0 OR 104:A/0 OR 62:a/0 OR 78:O/0 OR 213:J/0 OR 132:N/0 OR 128:H/0 OR 68:Q/0 OR 58:J/0 OR 72:J/0 OR 256:Q/0 OR 157:U/0 OR 90:H/0 OR 2:V/0 OR 297:M/0 OR 353:M/0 OR 195:Q/0 OR 374:Q/0 OR 351:H/0 OR 150:I/0 OR 673:N/0 OR 133:I/0 OR 112:U/0 OR 221:M/0 OR 306:L/0 OR 293:P/0 OR 10:Q/0 OR 189:S/0 OR 636:N/0 OR 426:Q/0 OR 594:N/0 OR 682:N/0 OR 181:B/0 OR 196:b/0 OR 53:G/0 OR 25:g/0 OR 108:g/0 OR 12:G/0 ) AND .CA' - -var nestedSyntax = '(( /0 AND (( :1 AND (28 OR 31 OR 35 OR 53 OR 55 OR 61 OR 66 OR 76 OR 81 OR 101 OR 142 OR 148 OR 158 OR 186 OR 202) ) OR ( :2 AND (3 OR 66 OR 81 OR 83 OR 104 OR 155 OR 177 OR 191) ) OR ( :3 AND (98 OR 101) ) OR ( :4 AND (25 OR 197 OR 202) ) OR ( :5 AND (57 OR 74 OR 90 OR 131 OR 203) ) OR ( :6 AND (25 OR 30 OR 76 OR 85 OR 92 OR 109 OR 112 OR 150 OR 155 OR 167 OR 178 OR 181) ) OR ( :7 AND (46 OR 59 OR 71 OR 81 OR 94 OR 112) ) OR ( :8 AND (19 OR 48 OR 49 OR 55 OR 67 OR 101 OR 116 OR 122 OR 163 OR 177 OR 179 OR 199 OR 208 OR 209 OR 217) ) OR ( :9 AND (3 OR 4 OR 78 OR 109 OR 127 OR 159 OR 161 OR 204) ) OR ( :O AND (11 OR 16 OR 23 OR 29 OR 34 OR 39 OR 54 OR 70 OR 76 OR 78 OR 86 OR 103 OR 116 OR 125 OR 130 OR 132 OR 146 OR 155 OR 164 OR 171 OR 181 OR 190 OR 193 OR 197 OR 210 OR 211 OR 212 OR 237 OR 250 OR 280 OR 285 OR 315 OR 317 OR 322 OR 327 OR 334 OR 339 OR 354 OR 365 OR 374) ) OR ( :H AND (5 OR 17 OR 20 OR 21 OR 24 OR 41 OR 49 OR 55 OR 72 OR 75 OR 79 OR 90 OR 94 OR 110 OR 111 OR 123 OR 126 OR 128 OR 143 OR 149 OR 154 OR 193 OR 221 OR 232 OR 271 OR 278 OR 280 OR 321 OR 329 OR 345 OR 351) ) OR ( :M AND (1 OR 6 OR 7 OR 19 OR 38 OR 39 OR 53 OR 61 OR 66 OR 70 OR 85 OR 97 OR 124 OR 133 OR 145 OR 162 OR 164 OR 177 OR 192 OR 196 OR 221 OR 251 OR 256 OR 267 OR 270 OR 272 OR 295 OR 297 OR 313 OR 326 OR 327 OR 328 OR 335 OR 353 OR 356) ) OR ( :N AND (6 OR 13 OR 21 OR 30 OR 44 OR 46 OR 49 OR 53 OR 58 OR 62 OR 71 OR 77 OR 102 OR 132 OR 136 OR 137 OR 140 OR 159 OR 207 OR 208 OR 219 OR 244 OR 253 OR 269 OR 274 OR 315 OR 318 OR 328 OR 331 OR 334 OR 370 OR 376 OR 380 OR 389 OR 400 OR 402 OR 428 OR 448 OR 485 OR 490 OR 519 OR 530 OR 548 OR 577 OR 594 OR 630 OR 636 OR 638 OR 660 OR 666 OR 669 OR 673 OR 674 OR 682 OR 685 OR 688 OR 705 OR 712 OR 716 OR 720 OR 734 OR 785 OR 808) ) OR ( :L AND (5 OR 8 OR 20 OR 40 OR 52 OR 63 OR 65 OR 70 OR 79 OR 99 OR 101 OR 108 OR 112 OR 131 OR 144 OR 152 OR 154 OR 157 OR 165 OR 197 OR 203 OR 205 OR 236 OR 238 OR 243 OR 255 OR 257 OR 259 OR 270 OR 278 OR 279 OR 280 OR 295 OR 305 OR 306 OR 317 OR 334) ) OR ( :C AND (17 OR 34 OR 41 OR 44 OR 96 OR 99 OR 100 OR 103 OR 104 OR 131 OR 148 OR 195 OR 214 OR 232) ) OR ( :B AND (44 OR 56 OR 90 OR 105 OR 110 OR 160 OR 181 OR 183 OR 225 OR 226) ) OR ( :b AND (30 OR 57 OR 82 OR 96 OR 116 OR 121 OR 148 OR 181 OR 196 OR 197 OR 211 OR 225) ) OR ( :c AND (35 OR 44 OR 49 OR 56 OR 60 OR 61 OR 64 OR 69 OR 117 OR 120 OR 155 OR 179 OR 207 OR 214 OR 228) ) OR ( :I AND (5 OR 18 OR 24 OR 27 OR 28 OR 44 OR 55 OR 56 OR 59 OR 74 OR 97 OR 133 OR 139 OR 148 OR 149 OR 150 OR 156 OR 175 OR 187 OR 205 OR 206 OR 210 OR 223 OR 248 OR 254 OR 281 OR 309 OR 317 OR 323) ) OR ( :T AND (9 OR 40 OR 53 OR 55 OR 105 OR 109 OR 115 OR 135 OR 141 OR 182 OR 197 OR 199 OR 210 OR 214 OR 218 OR 227 OR 230 OR 233 OR 239 OR 249 OR 261) ) OR ( :X AND (1 OR 4 OR 17 OR 43 OR 45 OR 57 OR 81 OR 123) ) OR ( :J AND (3 OR 13 OR 15 OR 18 OR 33 OR 52 OR 53 OR 58 OR 59 OR 72 OR 77 OR 86 OR 101 OR 105 OR 113 OR 120 OR 127 OR 134 OR 154 OR 161 OR 162 OR 166 OR 175 OR 181 OR 199 OR 204 OR 210 OR 213 OR 224 OR 229 OR 240 OR 249 OR 255 OR 274 OR 278 OR 302 OR 326 OR 338 OR 354 OR 373) ) OR ( :Q AND (10 OR 11 OR 37 OR 46 OR 50 OR 68 OR 77 OR 78 OR 90 OR 92 OR 94 OR 104 OR 106 OR 111 OR 113 OR 115 OR 125 OR 135 OR 136 OR 138 OR 140 OR 144 OR 147 OR 164 OR 195 OR 219 OR 246 OR 252 OR 256 OR 258 OR 267 OR 270 OR 275 OR 280 OR 282 OR 288 OR 299 OR 311 OR 355 OR 372 OR 374 OR 375 OR 377 OR 389 OR 398 OR 401 OR 404 OR 425 OR 426 OR 429 OR 430) ) OR ( :E AND (20 OR 22 OR 33 OR 45 OR 74 OR 82 OR 109 OR 124 OR 138 OR 206 OR 210 OR 213 OR 217 OR 222 OR 225) ) OR ( :e AND (20 OR 45 OR 48 OR 49 OR 53 OR 56 OR 69 OR 75 OR 110 OR 120 OR 134 OR 148 OR 158 OR 222 OR 232) ) OR ( :K AND (2 OR 8 OR 19 OR 23 OR 28 OR 29 OR 31 OR 66 OR 73 OR 82 OR 88 OR 113 OR 125 OR 133 OR 160 OR 219 OR 227 OR 233 OR 235 OR 269 OR 276 OR 278 OR 280 OR 293 OR 303 OR 323 OR 329 OR 332 OR 333 OR 346 OR 357) ) OR ( :V AND (2 OR 14 OR 34 OR 43 OR 52 OR 70 OR 71 OR 82 OR 86 OR 88 OR 99 OR 118 OR 126 OR 154 OR 156 OR 158 OR 176 OR 188 OR 196 OR 204 OR 219 OR 244) ) OR ( :A AND (24 OR 32 OR 42 OR 64 OR 85 OR 101 OR 104 OR 109 OR 141 OR 153 OR 166 OR 168 OR 221 OR 230 OR 243) ) OR ( :a AND (14 OR 17 OR 35 OR 44 OR 59 OR 62 OR 68 OR 120 OR 131 OR 136 OR 146 OR 170 OR 177 OR 180) ) OR ( :l AND (27 OR 59 OR 65 OR 91 OR 95 OR 128) ) OR ( :R AND (20 OR 34 OR 69 OR 86 OR 117 OR 121 OR 124 OR 133 OR 156 OR 159 OR 169 OR 192 OR 248 OR 249 OR 261 OR 270 OR 280 OR 282 OR 295 OR 339 OR 341 OR 345 OR 349 OR 355 OR 357 OR 358 OR 363 OR 364 OR 371 OR 383 OR 387 OR 391) ) OR ( :h AND (81 OR 175) ) OR ( :Z AND (30 OR 124 OR 295 OR 315 OR 353 OR 359 OR 416 OR 432 OR 449 OR 451 OR 510 OR 524 OR 538 OR 542 OR 550 OR 586 OR 635 OR 637 OR 655 OR 660 OR 722 OR 740) ) OR ( :D AND (4 OR 25 OR 37 OR 53 OR 67 OR 69 OR 85 OR 97 OR 109 OR 121 OR 128 OR 141 OR 179 OR 181 OR 191 OR 202 OR 204 OR 228) ) OR ( :d AND (12 OR 45 OR 62 OR 70 OR 72 OR 73 OR 111 OR 124 OR 130 OR 133 OR 151 OR 158 OR 170 OR 172 OR 194 OR 195 OR 210 OR 222) ) OR ( :U AND (6 OR 12 OR 16 OR 34 OR 35 OR 36 OR 42 OR 45 OR 48 OR 56 OR 79 OR 86 OR 90 OR 95 OR 109 OR 112 OR 114 OR 118 OR 120 OR 129 OR 134 OR 138 OR 153 OR 157 OR 160 OR 168 OR 188 OR 205 OR 213 OR 226 OR 231 OR 232 OR 254) ) OR ( :P AND (7 OR 25 OR 79 OR 95 OR 106 OR 107 OR 112 OR 116 OR 161 OR 165 OR 180 OR 191 OR 199 OR 211 OR 219 OR 232 OR 250 OR 267 OR 275 OR 290 OR 292 OR 293 OR 298 OR 302 OR 331 OR 343 OR 357 OR 364 OR 369 OR 376 OR 404 OR 408) ) OR ( :k AND (33 OR 39 OR 65 OR 69 OR 72 OR 87 OR 102 OR 120 OR 141 OR 161 OR 174 OR 183) ) OR ( :j AND (9 OR 59 OR 80 OR 83 OR 112) ) OR ( :S AND (7 OR 30 OR 51 OR 56 OR 70 OR 85 OR 90 OR 95 OR 118 OR 130 OR 139 OR 171 OR 181 OR 189 OR 194 OR 199 OR 227 OR 240 OR 244 OR 248 OR 252 OR 259 OR 263 OR 269 OR 284 OR 331 OR 337 OR 342 OR 353 OR 355 OR 388 OR 401 OR 403 OR 418 OR 428) ) OR ( :W AND (13 OR 27 OR 83 OR 93 OR 103 OR 131 OR 170 OR 185 OR 197) ) OR ( :F AND (33 OR 123 OR 136 OR 137 OR 145 OR 157 OR 171 OR 199 OR 209 OR 211) ) OR ( :f AND (4 OR 18 OR 62 OR 75 OR 82 OR 117 OR 125 OR 132 OR 216) ) OR ( :G AND (12 OR 49 OR 52 OR 53 OR 102 OR 121 OR 123 OR 140 OR 145 OR 155 OR 195 OR 236) ) OR ( :g AND (1 OR 25 OR 49 OR 65 OR 80 OR 94 OR 108 OR 114 OR 135 OR 138 OR 171 OR 225) ) OR ( :i AND (133 OR 170 OR 179) )) ) ) AND .CA' - -stage.loadFile('rcsb://3jco').then(function (o) { - o.addRepresentation('cartoon', { - colorScheme: 'uniform' - }) - - o.addRepresentation('spacefill', { - sele: flatSyntax, - name: 'flatSyntaxRes', - color: 'blue', - opacity: 0.5 - }) - - o.addRepresentation('spacefill', { - sele: nestedSyntax, - name: 'nestedSyntaxRes', - color: 'red', - opacity: 0.5 - }) - - stage.autoView() -}) diff --git a/examples/examples/scripts/selection/ring.js b/examples/examples/scripts/selection/ring.js deleted file mode 100644 index d3eec6698..000000000 --- a/examples/examples/scripts/selection/ring.js +++ /dev/null @@ -1,10 +0,0 @@ - -stage.loadFile('data://4w93.mmtf').then(function (o) { - o.addRepresentation('licorice', { sele: '[3L9]' }) - - o.addRepresentation('spacefill', { - radius: 0.5, sele: '[3L9] and ring' - }) - - stage.autoView() -}) diff --git a/examples/examples/scripts/selection/spatialHash.js b/examples/examples/scripts/selection/spatialHash.js deleted file mode 100644 index cb3535635..000000000 --- a/examples/examples/scripts/selection/spatialHash.js +++ /dev/null @@ -1,38 +0,0 @@ - -stage.loadFile('rcsb://3sn6.mmtf', { - defaultRepresentation: false -}).then(function (o) { - o.addRepresentation('cartoon', { quality: 'low' }) - stage.autoView() - - var radius = 8 - var spacefillRepr = o.addRepresentation('ball+stick', { sele: 'NONE' }) - - function getCenterArray () { - var position = new NGL.Vector3() - position.copy(stage.viewerControls.position) - return position.negate() - } - - var sphereBuffer = new NGL.SphereBuffer({ - position: new Float32Array(getCenterArray().toArray()), - color: new Float32Array([ 1, 0.5, 1 ]), - radius: new Float32Array([ radius ]) - }) - o.addBufferRepresentation(sphereBuffer, { opacity: 0.5 }) - - var prevSele = '' - var prevPos = new NGL.Vector3(Infinity, Infinity, Infinity) - stage.viewerControls.signals.changed.add(function () { - var pos = getCenterArray() - if (pos.distanceTo(prevPos) > 0.1) { - sphereBuffer.setAttributes({ 'position': pos.toArray() }) - prevPos = pos - var sele = o.structure.getAtomSetWithinPoint(pos, radius).toSeleString() - if (sele !== prevSele) { - spacefillRepr.setSelection(sele) - prevSele = sele - } - } - }) -}) diff --git a/examples/examples/scripts/selection/sstruc.js b/examples/examples/scripts/selection/sstruc.js deleted file mode 100644 index 543eaf735..000000000 --- a/examples/examples/scripts/selection/sstruc.js +++ /dev/null @@ -1,9 +0,0 @@ - -stage.loadFile('data://1crn.pdb').then(function (o) { - o.addRepresentation('backbone', { color: 'sstruc' }) - o.addRepresentation('rocket', { sele: 'helix', color: 'sstruc' }) - o.addRepresentation('cartoon', { sele: 'sheet', color: 'sstruc' }) - o.addRepresentation('tube', { sele: 'turn', color: 'sstruc' }) - - stage.autoView() -}) diff --git a/examples/examples/scripts/showcase/chlorellaVirus.js b/examples/examples/scripts/showcase/chlorellaVirus.js deleted file mode 100644 index 66928fe9a..000000000 --- a/examples/examples/scripts/showcase/chlorellaVirus.js +++ /dev/null @@ -1,14 +0,0 @@ - -stage.loadFile('data://1M4X.cif').then(function (o) { - o.addRepresentation('surface', { - sele: 'polymer', - assembly: 'BU1', - surfaceType: 'sas', - probeRadius: 0.1, - scaleFactor: 0.05, - colorScheme: 'atomindex', - colorScale: 'PiYG', - useWorker: false - }) - stage.tasks.onZeroOnce(function () { stage.autoView() }) -}) diff --git a/examples/examples/scripts/showcase/electrostatic-apbs.js b/examples/examples/scripts/showcase/electrostatic-apbs.js deleted file mode 100644 index bc81c1909..000000000 --- a/examples/examples/scripts/showcase/electrostatic-apbs.js +++ /dev/null @@ -1,50 +0,0 @@ - -stage.loadFile('data://1crn_apbs.pqr').then(function (o) { - o.addRepresentation('cartoon', { - colorScheme: 'partialCharge', - colorScale: 'rwb' - }) - o.addRepresentation('licorice', { - colorScheme: 'partialCharge', - colorScale: 'rwb' - }) - - o.autoView() -}) - -stage.loadFile('data://1crn_apbs_pot.dx.gz').then(function (o) { - o.addRepresentation('dot', { - thresholdType: 'value', - thresholdMin: -5, - thresholdMax: 5, - thresholdOut: true, - dotType: 'sphere', - radius: 'abs-value', - scale: 0.001, - visible: true, - colorScheme: 'value', - colorScale: 'rwb' - }) - - o.addRepresentation('surface', { - isolevelType: 'value', - isolevel: -0.4, - smooth: 1, - color: 'red', - opacity: 0.6, - side: 'back', - opaqueBack: false - }) - - o.addRepresentation('surface', { - isolevelType: 'value', - isolevel: 0.4, - smooth: 1, - color: 'blue', - opacity: 0.6, - side: 'front', - opaqueBack: false - }) - - stage.autoView() -}) diff --git a/examples/examples/scripts/showcase/ferredoxin.js b/examples/examples/scripts/showcase/ferredoxin.js deleted file mode 100644 index f5bb81264..000000000 --- a/examples/examples/scripts/showcase/ferredoxin.js +++ /dev/null @@ -1,48 +0,0 @@ - -stage.loadFile('data://1blu.mmtf').then(function (o) { - // show protein backbone - o.addRepresentation('backbone', { - color: 'skyblue' - }) - - // show iron-sulfur clusters enlarged by a factor of 2 - o.addRepresentation('ball+stick', { - sele: 'SF4', - scale: 2, - color: 'element' - }) - - // show sidechains of cysteins "bond" to iron-sulfur clusters - o.addRepresentation('licorice', { - sele: 'CYS and sidechainAttached and not 57', - color: 'yellow' - }) - - // show `.SG` atoms of cysteins "bond" to iron-sulfur clusters - o.addRepresentation('spacefill', { - sele: 'CYS and .SG and not 57', - color: 'yellow', - radius: 0.3 - }) - - // use distance representation with labels switched off - // to indicate "bonds" to cysteine sidechains - o.addRepresentation('distance', { - atomPair: [ - [ '18:A.SG', '102:A.FE1' ], - [ '37:A.SG', '102:A.FE3' ], - [ '40:A.SG', '102:A.FE4' ], - [ '49:A.SG', '102:A.FE2' ], - - [ '8:A.SG', '101:A.FE3' ], - [ '11:A.SG', '101:A.FE4' ], - [ '14:A.SG', '101:A.FE2' ], - [ '53:A.SG', '101:A.FE1' ] - ], - scale: 0.5, - color: 'element', - labelVisible: false - }) - - stage.autoView() -}) diff --git a/examples/examples/scripts/showcase/ferritin.js b/examples/examples/scripts/showcase/ferritin.js deleted file mode 100644 index ad098cb63..000000000 --- a/examples/examples/scripts/showcase/ferritin.js +++ /dev/null @@ -1,37 +0,0 @@ - -// 4Y08 ONE MINUTE IRON LOADED HUMAN H FERRITIN -// 4ZJK FIVE MINUTES IRON LOADED HUMAN H FERRITIN -// 4OYN Fifteen minutes iron loaded human H ferritin - -Promise.all([ - - stage.loadFile('data://4Y08.pdb', { - defaultAssembly: 'BU1' - }).then(function (o) { - o.addRepresentation('rope', { - color: 'lightgreen', radius: 'sstruc', scale: 4.0 - }) - o.addRepresentation('spacefill', { - sele: '_Fe', color: 'red', scale: 1.0, opacity: 1.0 - }) - }), - - stage.loadFile('data://4ZJK.pdb', { - defaultAssembly: 'BU1' - }).then(function (o) { - o.addRepresentation('spacefill', { - sele: '_Fe', color: 'orange', scale: 1.0, opacity: 1.0 - }) - }), - - stage.loadFile('data://4OYN.pdb', { - defaultAssembly: 'BU1' - }).then(function (o) { - o.addRepresentation('spacefill', { - sele: '_Fe', color: 'yellow', scale: 1.0, opacity: 1.0 - }) - }) - -]).then(function () { - stage.autoView() -}) diff --git a/examples/examples/scripts/showcase/gfp.js b/examples/examples/scripts/showcase/gfp.js deleted file mode 100644 index 30281d940..000000000 --- a/examples/examples/scripts/showcase/gfp.js +++ /dev/null @@ -1,32 +0,0 @@ - -stage.loadFile('data://1ema.cif').then(function (o) { - o.addRepresentation('cartoon', { - color: 'white', - smoothSheet: true, - opacity: 0.3, - depthWrite: false, - side: 'front', - quality: 'high' - }) - - o.addRepresentation('licorice', { - sele: '64-68', - scale: 3, - color: 'green' - }) - - o.addRepresentation('point', { - sele: '64-68', - opacity: 0.15, - color: 'green', - useTexture: true, - pointSize: 40, - edgeBleach: 1, - alphaTest: 0, - depthWrite: false - }) - - var pa = o.structure.getView(new NGL.Selection('.CA')).getPrincipalAxes() - stage.animationControls.rotate(pa.getRotationQuaternion(), 0) - stage.autoView() -}) diff --git a/examples/examples/scripts/showcase/hiv.js b/examples/examples/scripts/showcase/hiv.js deleted file mode 100644 index cf236a82f..000000000 --- a/examples/examples/scripts/showcase/hiv.js +++ /dev/null @@ -1,104 +0,0 @@ - -function addElement (el) { - Object.assign(el.style, { - position: 'absolute', - zIndex: 10 - }) - stage.viewer.container.appendChild(el) -} - -function createElement (name, properties, style) { - var el = document.createElement(name) - Object.assign(el, properties) - Object.assign(el.style, style) - return el -} - -stage.loadFile('rcsb://3j3q.mmtf').then(function (o) { - o.autoView() - - var point = o.addRepresentation('point') - - var surface = o.addRepresentation('surface', { - surfaceType: 'sas', - smooth: 2, - scaleFactor: 0.2, - colorScheme: 'chainindex', - opaqueBack: false - }) - - var cartoon = o.addRepresentation('cartoon', { - sele: ':f0 or :f1 or :f2 or :f3 or :f4 or :f5', - colorScheme: 'chainindex' - }) - - o.addRepresentation('ball+stick', { - sele: ':f0', - colorScheme: 'element' - }) - - o.addRepresentation('rocket', { - sele: ':f0', - colorScheme: 'chainindex' - }) - - var pointButton = createElement('input', { - type: 'button', - value: 'toggle points' - }, { top: '12px', left: '12px' }) - pointButton.onclick = function (e) { - point.toggleVisibility() - } - addElement(pointButton) - - var surfaceButton = createElement('input', { - type: 'button', - value: 'toggle surface' - }, { top: '36px', left: '12px' }) - surfaceButton.onclick = function (e) { - surface.toggleVisibility() - } - addElement(surfaceButton) - - var cartoonButton = createElement('input', { - type: 'button', - value: 'toggle cartoon' - }, { top: '60px', left: '12px' }) - cartoonButton.onclick = function (e) { - cartoon.toggleVisibility() - } - addElement(cartoonButton) - - var centerAllButton = createElement('input', { - type: 'button', - value: 'center all' - }, { top: '96px', left: '12px' }) - centerAllButton.onclick = function (e) { - stage.autoView() - } - addElement(centerAllButton) - - var centerSubunitButton = createElement('input', { - type: 'button', - value: 'center subunit' - }, { top: '120px', left: '12px' }) - centerSubunitButton.onclick = function (e) { - o.autoView(':f0 or :f1 or :f2 or :f3 or :f4 or :f5') - } - addElement(centerSubunitButton) - - addElement(createElement('span', { - innerText: 'surface transparency' - }, { top: '156px', left: '12px', color: 'lightgrey' })) - var opacityRange = createElement('input', { - type: 'range', - value: 0, - min: 0, - max: 100, - step: 1 - }, { top: '172px', left: '12px' }) - opacityRange.oninput = function (e) { - surface.setParameters({ opacity: 1 - (e.target.value / 100) }) - } - addElement(opacityRange) -}) diff --git a/examples/examples/scripts/showcase/norovirus.js b/examples/examples/scripts/showcase/norovirus.js deleted file mode 100644 index c09f45e64..000000000 --- a/examples/examples/scripts/showcase/norovirus.js +++ /dev/null @@ -1,33 +0,0 @@ - -// Inside the virus capsid is the 65 base pair structure of a conserved -// retroviral RNA packaging element from the Moloney murine leukemia virus -// for size comparison. The capsid is composed of 60 identical protein and -// normally hosts a RNA genome of about 7.500 base pairs. - -stage.setParameters({ clipNear: 35 }) - -stage.loadFile('data://1IHM.pdb', { - defaultAssembly: 'BU1' -}).then(function (o) { - o.addRepresentation('rope', { - subdiv: 1, - radialSegments: 5, - quality: 'user', - colorScheme: 'chainindex', - radius: 1.0, - scale: 4.0 - }) - stage.autoView() -}) - -stage.loadFile('data://2L1F.pdb', { - firstModelOnly: true -}).then(function (o) { - o.addRepresentation('cartoon', { - color: 'white', aspectRatio: 2.5, scale: 2.0 - }) - o.addRepresentation('base', { - colorScheme: 'resname', radius: 0.7 - }) - stage.autoView() -}) diff --git a/examples/examples/scripts/showcase/qmean.js b/examples/examples/scripts/showcase/qmean.js deleted file mode 100644 index c741c282d..000000000 --- a/examples/examples/scripts/showcase/qmean.js +++ /dev/null @@ -1,79 +0,0 @@ - -function createElement (name, properties, style) { - var el = document.createElement(name) - Object.assign(el, properties) - Object.assign(el.style, style) - return el -} - -function createSelect (options, properties, style) { - var select = createElement('select', properties, style) - options.forEach(function (d) { - select.add(createElement('option', { - value: d[ 0 ], text: d[ 1 ] - })) - }) - return select -} - -function addElement (el) { - Object.assign(el.style, { - position: 'absolute', - zIndex: 10 - }) - stage.viewer.container.appendChild(el) -} - -Promise.all([ - - stage.loadFile('data://1crn.pdb'), - NGL.autoLoad('data://1crn_qmean_local_scores.txt', { - ext: 'csv', - delimiter: ' ', - comment: '#', - columnNames: true - }) - -]).then(function (ol) { - var protein = ol[ 0 ] - var qmean = ol[ 1 ].data - - var qmeanScheme = NGL.ColormakerRegistry.addScheme(function (params) { - this.domain = [ 0.5, 1 ] - this.scale = 'PuBu' - this.mode = 'rgb' - var scale = this.getScale() - this.atomColor = function (atom) { - var value = parseFloat(qmean[ atom.residueIndex ][ 12 ]) - return scale(value) - } - }) - - var cartoon = protein.addRepresentation('cartoon', { color: qmeanScheme }) - - var schemeSelect = createSelect( - [ - [ qmeanScheme, 'qmean' ], - [ 'sstruc', 'secondary structure' ] - ], - null, - { top: '1em', left: '1em' } - ) - schemeSelect.onchange = function (e) { - cartoon.setParameters({ colorScheme: e.target.value }) - } - - var centerButton = createElement( - 'button', - { innerText: 'Center' }, - { top: '3em', left: '1em' } - ) - centerButton.onclick = function (e) { - stage.autoView(1000) - } - - addElement(schemeSelect) - addElement(centerButton) - - stage.autoView() -}) diff --git a/examples/examples/scripts/showcase/rhodopsin.js b/examples/examples/scripts/showcase/rhodopsin.js deleted file mode 100644 index bbc3eb092..000000000 --- a/examples/examples/scripts/showcase/rhodopsin.js +++ /dev/null @@ -1,40 +0,0 @@ - -stage.loadFile('data://3pqr.pdb').then(function (o) { - o.addRepresentation('cartoon', { - color: 'residueindex', aspectRatio: 4, scale: 0.5 - }) - o.addRepresentation('rope', { - color: 'residueindex', visible: false - }) - o.addRepresentation('ball+stick', { - sele: '296 or RET', scale: 3, aspectRatio: 1.5 - }) - o.addRepresentation('surface', { - sele: 'RET', - opacity: 0.4, - useWorker: false - }) - o.addRepresentation('licorice', { - sele: '( ( 135 or 223 ) and sidechainAttached ) or ( 347 )', - scale: 3, - aspectRatio: 1.5 - }) - o.addRepresentation('contact', { - sele: '135 or 223 or 347', - contactType: 'polar', - scale: 0.7 - }) - o.addRepresentation('label', { - sele: '( 135 or 223 or 347 or 296 ) and .CB', - color: 'white', - scale: 1.7 - }) - o.addRepresentation('label', { - sele: 'RET and .C19', - color: 'white', - scale: 1.7, - labelType: 'resname' - }) - - stage.autoView() -}) diff --git a/examples/examples/scripts/showcase/ribosome.js b/examples/examples/scripts/showcase/ribosome.js deleted file mode 100644 index af3275489..000000000 --- a/examples/examples/scripts/showcase/ribosome.js +++ /dev/null @@ -1,44 +0,0 @@ - -stage.loadFile('data://4UJD.cif.gz').then(function (o) { - o.addRepresentation('cartoon', { - - color: 'rgb( 127, 191, 255 )', - sele: ':A2 or :A3 or :A4 or :AA or :AB or :AC or :AD or :AE or :AF or :AG or :AH or :AI or :AJ or :AK or :AL or :AM or :AN or :AO or :AP or :AQ or :AR or :AS or :AT or :AU or :AV or :AW or :AX or :AY or :AZ or :Aa or :Ab or :Ac or :Ad or :Ae or :Af or :Ag or :Ah or :Ai or :Aj or :Ak or :Al or :Am or :An or :Ao or :Ap or :Aq or :Ar or :As or :At or :Au', - name: '60S' - - }) - - o.addRepresentation('cartoon', { - - color: 'rgb( 255, 255, 127 )', - sele: ':C1 or :CA or :CB or :CC or :CD or :CE or :CF or :CG or :CH or :CI or :CJ or :CK or :CL or :CM or :CN or :CO or :CP or :CQ or :CR or :CS or :CT or :CU or :CV or :CW or :CX or :CY or :CZ or :Ca or :Cb or :Cc or :Cd or :Ce or :Cf or :Cg', - name: '40S' - - }) - - o.addRepresentation('spacefill', { - - color: 'rgb( 255, 127, 255 )', - sele: ':BC', - name: 'IRES' - - }) - - o.addRepresentation('spacefill', { - - color: 'rgb( 51, 255, 51 )', - sele: ':BA', - name: 'tRNA' - - }) - - o.addRepresentation('spacefill', { - - color: 'rgb( 255, 0, 0 )', - sele: ':BB', - name: 'EIF5B' - - }) - - o.autoView() -}) diff --git a/examples/examples/scripts/showcase/viruses.js b/examples/examples/scripts/showcase/viruses.js deleted file mode 100644 index 796f72d76..000000000 --- a/examples/examples/scripts/showcase/viruses.js +++ /dev/null @@ -1,80 +0,0 @@ - -function addElement (el) { - Object.assign(el.style, { - position: 'absolute', - zIndex: 10 - }) - stage.viewer.container.appendChild(el) -} - -function createElement (name, properties, style) { - var el = document.createElement(name) - Object.assign(el, properties) - Object.assign(el.style, style) - return el -} - -var pdbs = [ '1stm', '3nap', '1sid', '2ft1', '4cwu' ] -var colors = [ 'red', 'yellow', 'green', 'lightblue', 'violet' ] - -Promise.all(pdbs.map(function (id) { - return stage.loadFile('rcsb://' + id) -})).then(function (ol) { - ol.map(function (o, i) { - var s = o.structure - var bu1 = s.biomolDict.BU1 - o.setPosition(bu1.getCenter(s).negate()) - o.addRepresentation('surface', { - sele: 'polymer', - assembly: 'BU1', - color: colors[ i ], - scaleFactor: 0.10, - surfaceType: 'sas' - }) - o.addAnnotation(bu1.getCenter(s), o.name) - }) - - stage.tasks.onZeroOnce(function () { stage.autoView() }) - stage.setParameters({ clipNear: 50 }) - - addElement(createElement('span', { - innerText: 'near clip' - }, { top: '12px', left: '12px', color: 'lightgrey' })) - var clipRange = createElement('input', { - type: 'range', - value: 50, - min: 0, - max: 100, - step: 1 - }, { top: '28px', left: '12px' }) - clipRange.oninput = function (e) { - stage.setParameters({ clipNear: e.target.value }) - } - addElement(clipRange) - - function center () { - ol.map(function (o, i) { - var s = o.structure - var bu1 = s.biomolDict.BU1 - o.setPosition(bu1.getCenter(s).negate()) - }) - } - - var animateButton = createElement('input', { - type: 'button', - value: 'animate' - }, { top: '52px', left: '12px' }) - var pos = [ 1175, 875, 400, -200, -1000 ] - animateButton.onclick = function (e) { - center() - var ac = stage.animationControls - ol.map(function (o, i) { - var s = o.structure - var bu1 = s.biomolDict.BU1 - var p = bu1.getCenter(s) - p.x += pos[ i ] - ac.moveComponent(ol[ i ], p, 1500) - }) - } - addElement(animateButton) -}) diff --git a/examples/examples/scripts/test/1blu.js b/examples/examples/scripts/test/1blu.js deleted file mode 100644 index a7a76e1f1..000000000 --- a/examples/examples/scripts/test/1blu.js +++ /dev/null @@ -1,15 +0,0 @@ - -stage.loadFile('data://1blu.pdb').then(function (o) { - o.addRepresentation('cartoon', { sele: '*' }) - o.addRepresentation('backbone', { - sele: '*', - scale: 1.0, - aspectRatio: 1.5, - color: 'lightgreen' - }) - o.addRepresentation('licorice', { sele: '*', scale: 1.0 }) - - var center = o.getCenter('101') - var zoom = o.getZoom('101') - stage.animationControls.zoomMove(center, zoom, 0) -}) diff --git a/examples/examples/scripts/test/2buk.js b/examples/examples/scripts/test/2buk.js deleted file mode 100644 index c2c4d2229..000000000 --- a/examples/examples/scripts/test/2buk.js +++ /dev/null @@ -1,8 +0,0 @@ - -stage.loadFile('data://2buk.pdb').then(function (o) { - o.addRepresentation('backbone', { - lineOnly: true, - assembly: 'UNITCELL' - }) - stage.autoView() -}) diff --git a/examples/examples/scripts/test/alignment.js b/examples/examples/scripts/test/alignment.js deleted file mode 100644 index a640de702..000000000 --- a/examples/examples/scripts/test/alignment.js +++ /dev/null @@ -1,26 +0,0 @@ - -Promise.all([ - - stage.loadFile('data://3dqb.pdb', { - defaultAssembly: 'AU' - }).then(function (o) { - o.addRepresentation('cartoon', { color: 'lightgreen' }) - o.addRepresentation('ball+stick', { sele: 'hetero', color: 'lightgreen' }) - o.autoView() - return o - }), - - stage.loadFile('data://3sn6.pdb').then(function (o) { - o.addRepresentation('cartoon', { color: 'tomato' }) - o.addRepresentation('ball+stick', { sele: 'hetero', color: 'tomato' }) - o.autoView() - return o - }) - -]).then(function (ol) { - var s1 = ol[ 0 ].structure - var s2 = ol[ 1 ].structure - NGL.superpose(s1, s2, true) - ol[ 0 ].updateRepresentations({ position: true }) - ol[ 0 ].autoView() -}) diff --git a/examples/examples/scripts/test/alignment2.js b/examples/examples/scripts/test/alignment2.js deleted file mode 100644 index ab797360f..000000000 --- a/examples/examples/scripts/test/alignment2.js +++ /dev/null @@ -1,22 +0,0 @@ - -Promise.all([ - - stage.loadFile('data://1gzm.pdb').then(function (o) { - o.addRepresentation('cartoon', { color: 'lightgreen' }) - o.autoView() - return o - }), - - stage.loadFile('data://1u19.pdb').then(function (o) { - o.addRepresentation('cartoon', { color: 'tomato' }) - o.autoView() - return o - }) - -]).then(function (ol) { - var s1 = ol[ 0 ].structure - var s2 = ol[ 1 ].structure - NGL.superpose(s1, s2, true, ':A', ':A') - ol[ 0 ].updateRepresentations({ position: true }) - ol[ 0 ].autoView() -}) diff --git a/examples/examples/scripts/test/backboneTypeChange.js b/examples/examples/scripts/test/backboneTypeChange.js deleted file mode 100644 index 592341ff3..000000000 --- a/examples/examples/scripts/test/backboneTypeChange.js +++ /dev/null @@ -1,8 +0,0 @@ - -// test case for inter-chain backboneType changes - -stage.loadFile('data://4V60_A.pdb').then(function (o) { - o.addRepresentation('cartoon') - o.addRepresentation('licorice') - o.autoView() -}) diff --git a/examples/examples/scripts/test/concat.js b/examples/examples/scripts/test/concat.js deleted file mode 100644 index 91217db74..000000000 --- a/examples/examples/scripts/test/concat.js +++ /dev/null @@ -1,28 +0,0 @@ - -Promise.all([ - stage.loadFile('data://2vts-protein.pdb'), - stage.loadFile('data://2vts-docking.sdf') -]).then(function (ol) { - var cs = NGL.concatStructures( - 'concat', - ol[ 0 ].structure.getView(new NGL.Selection('not ligand')), - ol[ 1 ].structure.getView(new NGL.Selection('')) - ) - var comp = stage.addComponentFromObject(cs) - comp.addRepresentation('cartoon') - comp.addRepresentation('contact', { - masterModelIndex: 0, - weakHydrogenBond: true, - maxHbondDonPlaneAngle: 35, - sele: '/0 or /2' - }) - comp.addRepresentation('licorice', { - sele: 'ligand and /2', - multipleBond: 'offset' - }) - comp.addRepresentation('line', { - sele: '/0' - }) - comp.autoView('ligand') - stage.setFocus(95) -}) diff --git a/examples/examples/scripts/test/dashedCylinders.js b/examples/examples/scripts/test/dashedCylinders.js deleted file mode 100644 index 64ae3c8e4..000000000 --- a/examples/examples/scripts/test/dashedCylinders.js +++ /dev/null @@ -1,28 +0,0 @@ - -stage.loadFile('rcsb://1atp').then(function (o) { - o.addRepresentation('cartoon') - o.addRepresentation('licorice') - - var center = o.getCenter('355:E.O1G') - var zoom = o.getZoom('atp') - stage.animationControls.zoomMove(center, zoom, 0) - - var pos1 = [ 17.549999237060547, 8.53600025177002, -0.5149999856948853 ] - - var pos2 = [ - [ 19.740999221801758, 6.551000118255615, -0.546999990940094 ], - [ 19.969999313354492, 5.958000183105469, -1.8380000591278076 ], - [ 18.88599967956543, 6.414999961853027, -2.821000099182129 ], - [ 14.675999641418457, 8.154000282287598, -3.7300000190734863 ], - [ 13.555000305175781, 6.9029998779296875, -0.13099999725818634 ] - ] - - var shape = new NGL.Shape('shape', { dashedCylinder: true, radialSegments: 60 }) - - for (var i = 0; i < pos2.length; i++) { - shape.addCylinder(pos1, pos2[i], [ 1, 1, 0.4 ], 0.05, 'My test ' + i) - } - var shapeComp = stage.addComponentFromObject(shape) - shapeComp.addRepresentation('buffer') - shapeComp.autoView() -}) diff --git a/examples/examples/scripts/test/explode.js b/examples/examples/scripts/test/explode.js deleted file mode 100644 index b2be0062a..000000000 --- a/examples/examples/scripts/test/explode.js +++ /dev/null @@ -1,56 +0,0 @@ - -function addElement (el) { - Object.assign(el.style, { - position: 'absolute', - zIndex: 10 - }) - stage.viewer.container.appendChild(el) -} - -function createElement (name, properties, style) { - var el = document.createElement(name) - Object.assign(el, properties) - Object.assign(el.style, style) - return el -} - -stage.loadFile('data://3SN6.cif').then(function (o) { - var s = o.structure - var c = s.atomCenter() - var chainComps = [] - - s.eachChain(function (cp) { - if (!cp.entity.isPolymer()) return - - var sele = ':' + cp.chainname - var sc = s.getView(new NGL.Selection(sele)) - var oc = stage.addComponentFromObject(sc, { name: o.name + sele }) - oc.addRepresentation('cartoon') - chainComps.push(oc) - - var cc = sc.atomCenter() - cc.sub(c).normalize().multiplyScalar(30) - oc.setPosition(cc) - }) - - stage.autoView() - - addElement(createElement('span', { - innerText: 'explode' - }, { top: '12px', left: '12px', color: 'lightgrey' })) - var explodeRange = createElement('input', { - type: 'range', - value: 30, - min: 1, - max: 100, - step: 1 - }, { top: '28px', left: '12px' }) - explodeRange.oninput = function (e) { - chainComps.forEach(function (oc) { - var cc = oc.structure.atomCenter() - cc.sub(c).normalize().multiplyScalar(e.target.value) - oc.setPosition(cc) - }) - } - addElement(explodeRange) -}) diff --git a/examples/examples/scripts/test/helixorient_issue-7.js b/examples/examples/scripts/test/helixorient_issue-7.js deleted file mode 100644 index 6b831c74b..000000000 --- a/examples/examples/scripts/test/helixorient_issue-7.js +++ /dev/null @@ -1,12 +0,0 @@ - -stage.loadFile('data://4YVS.cif', { - defaultAssembly: 'AU', - sele: '86-100:H' -}).then(function (o) { - o.addRepresentation('helixorient') - o.addRepresentation('rope', { - opacity: 0.4, side: 'front', smooth: 0 - }) - o.addRepresentation('licorice', { sele: 'backbone' }) - stage.autoView() -}) diff --git a/examples/examples/scripts/test/impostor.js b/examples/examples/scripts/test/impostor.js deleted file mode 100644 index 77bd0cdbc..000000000 --- a/examples/examples/scripts/test/impostor.js +++ /dev/null @@ -1,6 +0,0 @@ - -stage.loadFile('data://1crn.pdb').then(function (o) { - o.addRepresentation('ball+stick', { sele: '16', disableImpostor: true }) - o.addRepresentation('ball+stick', { sele: 'not 16' }) - o.autoView('16') -}) diff --git a/examples/examples/scripts/test/inter-bonds.js b/examples/examples/scripts/test/inter-bonds.js deleted file mode 100644 index c097be9e5..000000000 --- a/examples/examples/scripts/test/inter-bonds.js +++ /dev/null @@ -1,5 +0,0 @@ - -stage.loadFile('data://inter-bonds.pdb').then(function (o) { - o.addRepresentation('licorice') - o.autoView() -}) diff --git a/examples/examples/scripts/test/map-shift.js b/examples/examples/scripts/test/map-shift.js deleted file mode 100644 index e8503d917..000000000 --- a/examples/examples/scripts/test/map-shift.js +++ /dev/null @@ -1,35 +0,0 @@ - -Promise.all([ - - stage.loadFile('data://JMJD2DA-x336_event2.ccp4.gz'), - stage.loadFile('data://JMJD2DA-x336_event2.pdb') - -]).then(function (ol) { - var map = ol[ 0 ] - var struc = ol[ 1 ] - - struc.autoView('LIG') - - var surfRepr = map.addRepresentation('surface', { - boxSize: 10, - useWorker: false, - wrap: true, - color: 'skyblue', - contour: true - }) - - struc.addRepresentation('cartoon') - struc.addRepresentation('ball+stick', { sele: 'hetero' }) - - stage.setFocus(95) - - // remove default scroll mouse action - stage.mouseControls.remove('scroll') - - // change isolevel on mouse scroll - stage.mouseControls.add('scroll', function (stage, delta) { - var d = Math.sign(delta) / 5 - var l = surfRepr.getParameters().isolevel - surfRepr.setParameters({ isolevel: l + d }) - }) -}) diff --git a/examples/examples/scripts/test/molsurf-object.js b/examples/examples/scripts/test/molsurf-object.js deleted file mode 100644 index e84904ee2..000000000 --- a/examples/examples/scripts/test/molsurf-object.js +++ /dev/null @@ -1,12 +0,0 @@ - -NGL.autoLoad('data://1crn.pdb').then(function (structure) { - var molsurf = new NGL.MolecularSurface(structure) - var surf = molsurf.getSurface({ - type: 'av', - probeRadius: 1.4, - name: 'molsurf' - }) - var o = stage.addComponentFromObject(surf) - o.addRepresentation('surface') - o.autoView() -}) diff --git a/examples/examples/scripts/test/nci.js b/examples/examples/scripts/test/nci.js deleted file mode 100644 index 3b7ecc63d..000000000 --- a/examples/examples/scripts/test/nci.js +++ /dev/null @@ -1,473 +0,0 @@ - -function addElement (el) { - Object.assign(el.style, { - position: 'absolute', - zIndex: 10 - }) - stage.viewer.container.appendChild(el) -} - -function createElement (name, properties, style) { - var el = document.createElement(name) - Object.assign(el, properties) - Object.assign(el.style, style) - return el -} - -function createSelect (options, properties, style) { - var select = createElement('select', properties, style) - options.forEach(function (d) { - select.add(createElement('option', { - value: d[ 0 ], text: d[ 1 ] - })) - }) - return select -} - -function createFileButton (label, properties, style) { - var input = createElement('input', Object.assign({ - type: 'file' - }, properties), { display: 'none' }) - addElement(input) - var button = createElement('input', { - value: label, - type: 'button', - onclick: function () { input.click() } - }, style) - return button -} - -function loadStructure (input) { - stage.removeAllComponents() - return stage.loadFile(input).then(function (o) { - o.addRepresentation('ribbon') - o.addRepresentation('licorice', { - multipleBond: 'symmetric' - }) - o.addRepresentation('contact', { - weakHydrogenBond: true, - waterHydrogenBond: true, - backboneHydrogenBond: true, - hydrophobic: true, - saltBridge: true - }) - stage.setFocus(0) - stage.autoView() - }) -} - -function loadExample (input) { - stage.removeAllComponents() - return stage.loadFile('rcsb://' + input.pdbid).then(function (o) { - var sele = '(' + input.sele1 + ') or (' + input.sele2 + ')' - var groupSele = o.structure.getAtomSetWithinGroup(new NGL.Selection(sele)).toSeleString() - o.autoView(sele) - o.addRepresentation('ribbon', { - visible: false - }) - o.addRepresentation('ball+stick', { - multipleBond: 'symmetric', - sele: sele - }) - o.addRepresentation('licorice', { - radiusScale: 0.5, - multipleBond: 'symmetric', - sele: groupSele - }) - o.addRepresentation('line', { - multipleBond: 'symmetric', - linewidth: 3 - }) - o.addRepresentation('contact', { - weakHydrogenBond: true, - waterHydrogenBond: true, - backboneHydrogenBond: true, - hydrophobic: true, - saltBridge: true - }) - stage.setFocus(95) - }) -} - -// create tooltip element and add to document body -var tooltip = document.createElement('div') -Object.assign(tooltip.style, { - display: 'none', - position: 'fixed', - zIndex: 10, - pointerEvents: 'none', - backgroundColor: 'rgba( 0, 0, 0, 0.6 )', - color: 'lightgrey', - padding: '8px', - fontFamily: 'sans-serif' -}) -document.body.appendChild(tooltip) - -// remove default hoverPick mouse action -stage.mouseControls.remove('hoverPick') - -// listen to `hovered` signal to move tooltip around and change its text -stage.signals.hovered.add(function (pickingProxy) { - if (pickingProxy) { - if (pickingProxy.atom || pickingProxy.bond) { - var atom = pickingProxy.atom || pickingProxy.closestBondAtom - var vm = atom.structure.data['@valenceModel'] - if (vm && vm.idealValence) { - tooltip.innerHTML = `${pickingProxy.getLabel()}
-
- Atom: ${atom.qualifiedName()}
- ideal valence: ${vm.idealValence[atom.index]}
- ideal geometry: ${vm.idealGeometry[atom.index]}
- implicit charge: ${vm.implicitCharge[atom.index]}
- formal charge: ${atom.formalCharge === null ? '?' : atom.formalCharge}
- aromatic: ${atom.aromatic ? 'true' : 'false'}
- ` - } else if (vm && vm.charge) { - tooltip.innerHTML = `${pickingProxy.getLabel()}
-
- Atom: ${atom.qualifiedName()}
- vm charge: ${vm.charge[atom.index]}
- vm implicitH: ${vm.implicitH[atom.index]}
- vm totalH: ${vm.totalH[atom.index]}
- vm geom: ${vm.idealGeometry[atom.index]}
- formal charge: ${atom.formalCharge === null ? '?' : atom.formalCharge}
- aromatic: ${atom.aromatic ? 'true' : 'false'}
- ` - } else { - tooltip.innerHTML = `${pickingProxy.getLabel()}` - } - } else { - tooltip.innerHTML = `${pickingProxy.getLabel()}` - } - var mp = pickingProxy.mouse.position - tooltip.style.bottom = window.innerHeight - mp.y + 3 + 'px' - tooltip.style.left = mp.x + 3 + 'px' - tooltip.style.display = 'block' - } else { - tooltip.style.display = 'none' - } -}) - -stage.signals.clicked.add(function (pickingProxy) { - if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) { - console.log(pickingProxy.atom || pickingProxy.closestBondAtom) - } -}) - -function setTestOptions () { - testSelect.innerHTML = '' - testSelect.add(createElement('option', { value: '', text: '' })) - nciTests.forEach(function (d, i) { - testSelect.add(createElement('option', { - value: i, text: '[' + d.type + '] ' + d.info - })) - }) -} - -var loadStructureButton = createFileButton('load structure', { - accept: '.pdb,.cif,.ent,.gz,.mol2', - onchange: function (e) { - if (e.target.files[ 0 ]) { - testSelect.value = '' - testInfo.innerText = '' - loadStructure(e.target.files[ 0 ]) - } - } -}, { top: '12px', left: '12px' }) -addElement(loadStructureButton) - -var loadPdbidText = createElement('span', { - innerText: 'load pdb id' -}, { top: '50px', left: '12px', color: 'grey' }) -addElement(loadPdbidText) - -var loadPdbidInput = createElement('input', { - type: 'text', - title: 'press enter to load pdbid', - onkeypress: function (e) { - if (e.keyCode === 13) { - e.preventDefault() - testSelect.value = '' - testInfo.innerText = '' - loadStructure('rcsb://' + e.target.value) - } - } -}, { top: '70px', left: '12px', width: '120px' }) -addElement(loadPdbidInput) - -var testText = createElement('span', { - innerText: 'load example' -}, { top: '110px', left: '12px', color: 'grey' }) -addElement(testText) - -var testSelect = createSelect([], { - onchange: function (e) { - loadPdbidInput.value = '' - var input = nciTests[ e.target.value ] - testInfo.innerHTML = '' + - input.type + '
' + - input.info + '
' + - (input.desc ? (input.desc + '
') : '') + - input.sele1 + '
' + - input.sele2 + '' - loadExample(input) - } -}, { top: '130px', left: '12px', width: '130px' }) -addElement(testSelect) - -var testInfo = createElement('div', { - innerText: '' -}, { top: '150px', left: '12px', color: 'grey' }) -addElement(testInfo) - -var nciTests = JSON.parse(` -[ - { - "pdbid": "5pbf", - "sele1": "[8HJ] and 2003:A.N1", - "sele2": "ASN and 1944:A.OD1", - "type": "hydrogen-bond", - "info": "standard bromodomain fragment, acceptor" - }, - { - "pdbid": "5pbf", - "sele1": "[8HJ] and 2003:A.O1", - "sele2": "(ASN and 1944:A.ND2) or (HOH and 2115:A.O)", - "type": "hydrogen-bond", - "info": "standard bromodomain fragment, donor 1" - }, - { - "pdbid": "5pbf", - "sele1": "[8HJ] and 2003:A.O2", - "sele2": "HOH and 2217:A.O", - "type": "hydrogen-bond", - "info": "standard bromodomain fragment, donor 2" - }, - { - "pdbid": "4x0x", - "sele1": "CYS and 45:B.SG", - "sele2": "(LEU and 39:B.O) or (ARG and 116:B and (.NH1 or .NH2))", - "type": "hydrogen-bond", - "info": "cystein donor/acceptor" - }, - { - "pdbid": "2vts", - "sele1": "LZC and 1299:A.C21", - "sele2": "GLU and 81:A.O", - "type": "weak-hydrogen-bond", - "info": "common in kinase ligands" - }, - { - "pdbid": "1ac4", - "sele1": "TMT and 296:A.C5", - "sele2": "ASP and 235:A.OD2", - "type": "weak-hydrogen-bond", - "info": "ligand C donor, aspartate oxygen acceptor" - }, - { - "pdbid": "1gqu", - "sele1": "DA and 1:A.C8", - "sele2": "DT and 12:B.O2", - "type": "weak-hydrogen-bond", - "info": "hoogsteen base pairing" - }, - { - "pdbid": "1crn", - "sele1": "THR and 2:A.CA", - "sele2": "ILE and 33:A.O", - "type": "weak-hydrogen-bond", - "info": "beta sheet backbone contact" - }, - { - "pdbid": "191d", - "sele1": "DC and 6:B.C4'", - "sele2": "DC and 11:C.O4'", - "type": "weak-hydrogen-bond", - "info": "DNA backbone contact" - }, - { - "pdbid": "3sn6", - "sele1": "ARG and 131:R and (.NE or .NH1 or .NH2)", - "sele2": "TYR and 391:A and aromaticRing", - "type": "cation-pi", - "info": "receptor G protein interface" - }, - { - "pdbid": "4cwd", - "sele1": "[449] and 1385:A.NAK", - "sele2": "TYR and 177:A and aromaticRing", - "type": "cation-pi", - "info": "ligand quaternary amine, tyrosine ring" - }, - { - "pdbid": "3apv", - "sele1": "TP0 and 190:A.N1", - "sele2": "TYR and 37:A and aromaticRing", - "type": "cation-pi", - "info": "ligand tertiary amine, tyrosin ring" - }, - { - "pdbid": "3e5c", - "sele1": "SAM and 216:A.SD", - "sele2": "G and 36:A and (.C4 or .C5 or .N7 or .C8 or .N9)", - "type": "cation-pi", - "info": "ligand sulfonium, guanosine ring" - }, - { - "pdbid": "3eqa", - "sele1": "LYS and 132:A.NZ", - "sele2": "((TRP and 144:A) or (TYR and (140:A or 74:A)) and aromaticRing", - "type": "cation-pi", - "info": "lysine, tryptophan and tyrosine rings" - }, - { - "pdbid": "1g54", - "sele1": "FFB and 555:A and (.C15 or .C16 or .C17 or .C18 or .C19 or .C20)", - "sele2": "PHE and 131:A and aromaticRing", - "type": "pi-stacking", - "info": "ligand protein, t-shaped" - }, - { - "pdbid": "4x21", - "sele1": "[3WH] and 501:A.I17", - "sele2": "MET and 146:A.SD", - "type": "halogen-bond", - "info": "ligand iodine, methionine sulfur" - }, - { - "pdbid": "4lau", - "sele1": "W8X and 402:A.BR7", - "sele2": "THR and 113:A.OG1", - "type": "halogen-bond", - "info": "ligand bromine, threonine oxygen" - }, - { - "pdbid": "2vts", - "sele1": "ARG and 274:A and (.NH1 or .CZ or .NH2)", - "sele2": "GLU and 172:A and (.OE1 or .CD or .OE2)", - "type": "salt-bridge", - "info": "between ARG and GLU, hbonds hidden" - }, - { - "pdbid": "3apv", - "sele1": "TP0 and 190:A.N1", - "sele2": "ACY and 191:A and (.C or .OXT or .O)", - "type": "salt-bridge", - "info": "ligand tertiary amine, ligand carboxyl group" - }, - { - "pdbid": "1tbz", - "sele1": "[00Q] and 343:H and (.NH1 or .NH2 or .NEY)", - "sele2": "ASP and 189:H and (.OD1 or .OD2)", - "type": "salt-bridge", - "info": "ligand guainidine group, aspartate sidechain" - }, - { - "pdbid": "3nkk", - "sele1": "JLZ and 1:A and (.N12 or .N14)", - "sele2": "ASP and 189:A and (.OD1 or .OD2)", - "type": "salt-bridge", - "info": "ligand acetamidine group, aspartate sidechain" - }, - { - "pdbid": "3cup", - "sele1": "EPE and 302:A and (.O1S or .O2S or .O3S)", - "sele2": "ARG and 389:B and (.NE or .NH1 or .NH2)", - "type": "salt-bridge", - "info": "ligand sulfonic-acid group, arginine sidechain" - }, - { - "pdbid": "1vkj", - "sele1": "A3P and 602:A and (.O4P or .O5P or .O6P or .O5')", - "sele2": "LYS and 274:A.NZ", - "type": "salt-bridge", - "info": "ligand phospate group, lysine sidechain" - }, - { - "pdbid": "2bxh", - "sele1": "IOS and 1001:A and (.O1 or .O2 or .O3 or .O4)", - "sele2": "ARG and 410:A and (.NE or .NH1 or .NH2)", - "type": "salt-bridge", - "info": "ligand sulfate group, arginine sidechain" - }, - { - "pdbid": "1d66", - "sele1": "(DC and 13:D and (.OP1 or .OP2 or .O5')) or (DT and 12:D.O3')", - "sele2": "ARG and 46:B and (.NE or .NH1 or .NH2)", - "type": "salt-bridge", - "info": "DNA phospate group, arginine sidechain" - }, - { - "pdbid": "1ac8", - "sele1": "TMZ and 296:A.N3", - "sele2": "ASP and 235:A and (.OD1 or .OD2)", - "type": "salt-bridge", - "info": "ligand tertiary amine & weak hbonds, aspartate sidechain" - }, - { - "pdbid": "1blu", - "sele1": "SF4 and 102:A.FE2", - "sele2": "CYS and 49:A.SG", - "type": "metal-coordination", - "info": "cysteine to iron-sulfur cluster" - }, - { - "pdbid": "5vpw", - "sele1": "ICS and 602:A.MO1", - "sele2": "(HIS and 482:A.ND1) or (HCA and 601:A and (.O7 or .O6))", - "type": "metal-coordination", - "info": "molybdenum coordinated by histidine and ligand oxygens" - }, - { - "pdbid": "5k5h", - "sele1": "[ZN] and 502:A.ZN", - "sele2": "(CYS and 381:A.SG) or (CYS and 384:A.SG) or (HIS and 397:A.NE2) or (HIS and 401:A.NE2)", - "type": "metal-coordination", - "info": "zink coordinated by histidine and cysteine" - }, - { - "pdbid": "1n5w", - "sele1": "CUM and 3921:B.MO", - "sele2": "MCN and 3920:B and (.S7' or .S8')", - "type": "metal-coordination", - "info": "molybdenum coordinated by ligand sulfurs" - }, - { - "pdbid": "1n5w", - "sele1": "CUM and 3921:B.CU", - "sele2": "(CYS and 388:B.SG) or (HOH and 4334:B.O)", - "type": "metal-coordination", - "info": "copper coordinated by water and cysteine sidechain" - }, - { - "pdbid": "3hdi", - "sele1": "[CO] and 500:A.CO", - "sele2": "(GLU and 126:A and (.OE1 or .OE2)) or (HIS and 46:A.NE2) or (HIS and 50:A.NE2) or (ALA and 14:C.O)", - "type": "metal-coordination", - "info": "copper coordinated by backbone carbonyl, histidine and glutamate" - }, - { - "pdbid": "1en7", - "sele1": "[CA] and 403:A.CA", - "sele2": "(HOH and 447:A.O) or (HOH and 450:A.O) or (ASN and 62:A.OD2) or (ASP and 40:A.OD1)", - "type": "metal-coordination", - "info": "calcium coordinated by water, aspartate and asparagine" - }, - { - "pdbid": "5ph0", - "sele1": "[NI] and 402:A.NI", - "sele2": "(HOH and 598:A.O) or (HIS and 192:A.NE2) or (HIS and 280:A.NE2) or (GLU and 194:A.OE1) or (OGA and 404:A and (.O2' or .O1))", - "type": "metal-coordination", - "info": "nickel coordinated by ligand, water, glutamate and histidine" - }, - { - "pdbid": "1rla", - "sele1": "[MN] and 500:A.MN", - "sele2": "(HOH and 502:A.O) or (HIS and 101:A.ND1) or (ASP and (124:A or 128:A or 232:A) and .OD2)", - "type": "metal-coordination", - "info": "manganase coordinated by water, aspartate and histidine" - } -] -`) - -setTestOptions() diff --git a/examples/examples/scripts/test/orient.js b/examples/examples/scripts/test/orient.js deleted file mode 100644 index 02d47d12b..000000000 --- a/examples/examples/scripts/test/orient.js +++ /dev/null @@ -1,12 +0,0 @@ - -stage.loadFile('data://1blu.pdb').then(function (o) { - o.addRepresentation('hyperball', { sele: 'hetero' }) - o.addRepresentation('cartoon') - - stage.viewerControls.orient([ - 5.16, -0.86, -8.11, 0, - 3.05, 9.11, 0.97, 0, - 7.56, -3.08, 5.15, 0, - -28.57, -13.64, 3.36, 1 - ]) -}) diff --git a/examples/examples/scripts/test/pbc.js b/examples/examples/scripts/test/pbc.js deleted file mode 100644 index 059baa199..000000000 --- a/examples/examples/scripts/test/pbc.js +++ /dev/null @@ -1,9 +0,0 @@ - -stage.loadFile('data://pbc.gro').then(function (o) { - // FIXME pbc centering and removal for files other then trajectories - - o.addRepresentation('cartoon', { sele: 'backbone' }) - o.addRepresentation('spacefill', { sele: 'backbone' }) - o.addRepresentation('line') - o.autoView() -}) diff --git a/examples/examples/scripts/test/pdbDaminoacids.js b/examples/examples/scripts/test/pdbDaminoacids.js deleted file mode 100644 index ca74f84e6..000000000 --- a/examples/examples/scripts/test/pdbDaminoacids.js +++ /dev/null @@ -1,14 +0,0 @@ - -stage.loadFile('data://5gob.pdb', { - defaultAssembly: 'AU' -}).then(function (o) { - o.addRepresentation('cartoon', { - color: 'residueindex', - colorReverse: true - }) - o.addRepresentation('licorice', { - sele: 'ligand', - scale: 2.0 - }) - o.autoView() -}) diff --git a/examples/examples/scripts/test/pdbModifiedResidue.js b/examples/examples/scripts/test/pdbModifiedResidue.js deleted file mode 100644 index af19e3d29..000000000 --- a/examples/examples/scripts/test/pdbModifiedResidue.js +++ /dev/null @@ -1,12 +0,0 @@ - -stage.loadFile('data://2src.pdb').then(function (o) { - o.addRepresentation('cartoon', { - color: 'residueindex', - colorReverse: true - }) - o.addRepresentation('licorice', { - sele: 'ligand', - scale: 2.0 - }) - o.autoView() -}) diff --git a/examples/examples/scripts/test/pickingImage.js b/examples/examples/scripts/test/pickingImage.js deleted file mode 100644 index 386556efe..000000000 --- a/examples/examples/scripts/test/pickingImage.js +++ /dev/null @@ -1,19 +0,0 @@ - -stage.loadFile('data://3SN6.cif').then(function (o) { - o.addRepresentation('cartoon') - o.autoView() - - stage.viewer.getImage(true).then(function (blob) { - var size = stage.viewer.renderer.getSize() - var objectURL = window.URL.createObjectURL(blob) - var img = document.createElement('img') - img.src = objectURL - img.style.width = (size.width / 4) + 'px' - img.style.height = (size.height / 4) + 'px' - img.style.position = 'absolute' - img.style.top = '0px' - img.style.left = '0px' - img.style.zIndex = 10 - stage.viewer.container.appendChild(img) - }) -}) diff --git a/examples/examples/scripts/test/superposition.js b/examples/examples/scripts/test/superposition.js deleted file mode 100644 index 2d8464acd..000000000 --- a/examples/examples/scripts/test/superposition.js +++ /dev/null @@ -1,18 +0,0 @@ - -Promise.all([ - stage.loadFile('data://sp-ido40.mol2').then(function (o) { - o.addRepresentation('ball+stick') - return o - }), - - stage.loadFile('data://sp-after.mol2').then(function (o) { - o.addRepresentation('licorice') - return o - }) -]).then(function (ol) { - var sp = new NGL.Superposition(ol[0].structure, ol[1].structure) - sp.transform(ol[0].structure) - ol[0].updateRepresentations({ 'position': true }) - console.log(sp) - ol[1].autoView() -}) diff --git a/examples/examples/scripts/test/timing.js b/examples/examples/scripts/test/timing.js deleted file mode 100644 index a5478d8b0..000000000 --- a/examples/examples/scripts/test/timing.js +++ /dev/null @@ -1,18 +0,0 @@ - -// stage.loadFile( "data://3l5q.pdb", function( o ){ -stage.loadFile('data://4UJD.cif.gz').then(function (o) { -// stage.loadFile( "data://3j3y.cif.gz", function( o ){ - - // o.addRepresentation( "line", { color: "chainindex" } ); - // o.addRepresentation( "spacefill", { color: "chainindex" } ); - o.addRepresentation('cartoon', { color: 'chainindex' }) - // o.addRepresentation( "trace", { color: "chainindex" } ); - // o.addRepresentation( "point", { color: "chainindex" } ); - stage.autoView() - - console.timeEnd('test') - - console.time('render') - o.viewer.render() - console.timeEnd('render') -}) diff --git a/examples/examples/scripts/test/xray.js b/examples/examples/scripts/test/xray.js deleted file mode 100644 index 5c1028134..000000000 --- a/examples/examples/scripts/test/xray.js +++ /dev/null @@ -1,42 +0,0 @@ - -stage.setParameters({ - cameraType: 'orthographic', - mousePreset: 'coot' -}) - -stage.loadFile('data://3ek3.cif').then(function (o) { - o.addRepresentation('licorice', { - colorValue: 'yellow', - roughness: 1.0 - }) - o.autoView('FMN') - stage.setFocus(97) -}) - -stage.loadFile('data://3ek3-2fofc.map.gz').then(function (o) { - o.addRepresentation('surface', { - color: 'skyblue', - isolevel: 1.5, - boxSize: 10, - useWorker: false, - contour: true - }) -}) - -stage.loadFile('data://3ek3-fofc.map.gz').then(function (o) { - o.addRepresentation('surface', { - color: 'lightgreen', - isolevel: 3, - boxSize: 10, - useWorker: false, - contour: true - }) - o.addRepresentation('surface', { - color: 'tomato', - isolevel: 3, - negateIsolevel: true, - boxSize: 10, - useWorker: false, - contour: true - }) -}) diff --git a/examples/examples/test.html b/examples/examples/test.html deleted file mode 100644 index 0cdf9dd3f..000000000 --- a/examples/examples/test.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - NGL - test - - - - - - - -
- - diff --git a/examples/examples/webapp.html b/examples/examples/webapp.html deleted file mode 100644 index bf6ec429d..000000000 --- a/examples/examples/webapp.html +++ /dev/null @@ -1,64 +0,0 @@ - - - - NGL - webapp - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/parser/itp-parser.ts b/src/parser/itp-parser.ts deleted file mode 100644 index 7f8333c30..000000000 --- a/src/parser/itp-parser.ts +++ /dev/null @@ -1,192 +0,0 @@ -/** - * @file Top Parser - * @author Alexander Rose - * @private - */ - -import { Debug, Log, ParserRegistry } from '../globals' -import StructureParser from './structure-parser' -import { WaterNames } from '../structure/structure-constants' -import { - assignResidueTypeBonds, calculateBondsBetween, - calculateBondsWithin, getChainname -} from '../structure/structure-utils' - -const enum Mode { - System, - Molecules, - Moleculetype, - Atoms, - Bonds -} - -const reField = /\[ (.+) \]/ -const reWhitespace = /\s+/ - -class TopParser extends StructureParser { - get type () { return 'top' } - - _parse () { - // http://manual.gromacs.org/online/top.html - - if (Debug) Log.time('TopParser._parse ' + this.name) - - const s = this.structure - const sb = this.structureBuilder - - // - - const atomMap = s.atomMap - const bondStore = s.bondStore - - const atomStore = s.atomStore - atomStore.addField('partialCharge', 1, 'float32') - - const molecules: [string, number][] = [] - const moleculetypeDict: {[k: string]: {atoms: any[], bonds: any[] }} = {} - - let currentMoleculetype: { - atoms: [number, string, string, number][], - bonds: [number, number][] - } - let mode: number|undefined - - function _parseChunkOfLines (_i: number, _n: number, lines: string[]) { - for (let i = _i; i < _n; ++i) { - const line = lines[ i ] - let lt = line.trim() - - if (!lt || lt[0] === '*' || lt[0] === ';') { - continue - } - - if (lt.startsWith('#include')) { - throw new Error('TopParser: #include statements not allowed') - } - - const fieldMatch = line.match(reField) - if (fieldMatch !== null) { - const name = fieldMatch[1] - if (name === 'moleculetype') { - mode = Mode.Moleculetype - currentMoleculetype = { - atoms: [], - bonds: [] - } - } else if (name === 'atoms') { - mode = Mode.Atoms - } else if (name === 'bonds') { - mode = Mode.Bonds - } else if (name === 'system') { - mode = Mode.System - } else if (name === 'molecules') { - mode = Mode.Molecules - } else { - mode = undefined - } - continue - } - - const cIdx = lt.indexOf(';') - if (cIdx !== -1) { - lt = lt.substring(0, cIdx).trim() - } - if (mode === Mode.Moleculetype) { - const molName = lt.split(reWhitespace)[0] - moleculetypeDict[molName] = currentMoleculetype - } else if (mode === Mode.Atoms) { - const ls = lt.split(reWhitespace) - currentMoleculetype.atoms.push([ - parseInt(ls[2]), // resnr - ls[3], // residue - ls[4], // atom - parseFloat(ls[6]) // charge - ]) - } else if (mode === Mode.Bonds) { - const ls = lt.split(reWhitespace) - currentMoleculetype.bonds.push([ - parseInt(ls[0]), // ai - parseInt(ls[1]) // aj - ]) - } else if (mode === Mode.System) { - s.title = lt - } else if (mode === Mode.Molecules) { - const ls = lt.split(reWhitespace) - molecules.push([ - ls[0], // name - parseInt(ls[1]) // count - ]) - } - } - } - - this.streamer.eachChunkOfLines(function (lines/*, chunkNo, chunkCount */) { - _parseChunkOfLines(0, lines.length, lines) - }) - - let atomCount = 0 - let bondCount = 0 - molecules.forEach(function (val) { - const [name, molCount] = val - const molType = moleculetypeDict[name] - atomCount += molCount * molType.atoms.length - bondCount += molCount * molType.bonds.length - }) - - atomStore.resize(atomCount) - bondStore.resize(bondCount) - - let atomIdx = 0 - let resIdx = 0 - let chainidIdx = 0 - let chainnameIdx = 0 - let bondIdx = 0 - let atomOffset = 0 - let lastResno: number - - molecules.forEach(function (val) { - const [name, molCount] = val - const molType = moleculetypeDict[name] - const chainname = getChainname(chainnameIdx) - for (let i = 0; i < molCount; ++i) { - lastResno = -1 - const chainid = WaterNames.includes(name) ? chainname : getChainname(chainidIdx) - molType.atoms.forEach(function (atomData) { - const [resno, resname, atomname, charge] = atomData - if (resno !== lastResno) { - ++resIdx - } - atomStore.atomTypeId[atomIdx] = atomMap.add(atomname) - atomStore.serial[atomIdx] = atomIdx + 1 - atomStore.partialCharge[atomIdx] = charge - sb.addAtom(0, chainname, chainid, resname, resIdx + 1) - ++atomIdx - lastResno = resno - }) - molType.bonds.forEach(function (bondData) { - bondStore.atomIndex1[bondIdx] = atomOffset + bondData[0] - 1 - bondStore.atomIndex2[bondIdx] = atomOffset + bondData[1] - 1 - ++bondIdx - }) - ++chainidIdx - atomOffset += molType.atoms.length - } - ++chainnameIdx - }) - - bondStore.count = bondCount - - sb.finalize() - s.finalizeAtoms() - s.finalizeBonds() - calculateBondsWithin(s, true) - calculateBondsBetween(s, true, true) - assignResidueTypeBonds(s) - - if (Debug) Log.timeEnd('TopParser._parse ' + this.name) - } -} - -ParserRegistry.add('top', TopParser) - -export default TopParser diff --git a/src/stage/mouse-observer.ts b/src/stage/mouse-observer.ts index fdd9560bd..a58d3929c 100644 --- a/src/stage/mouse-observer.ts +++ b/src/stage/mouse-observer.ts @@ -62,7 +62,6 @@ export interface MouseSignals { moved: Signal // on move: deltaX, deltaY scrolled: Signal // on scroll: delta dragged: Signal // on drag: deltaX, deltaY - draggedXY: Signal //on drag: x0, y0, x1, y1 dropped: Signal // on drop clicked: Signal // on click hovered: Signal // on hover @@ -107,7 +106,6 @@ class MouseObserver { moved: new Signal(), scrolled: new Signal(), dragged: new Signal(), - draggedXY: new Signal(), dropped: new Signal(), clicked: new Signal(), hovered: new Signal(), @@ -409,10 +407,6 @@ class MouseObserver { this.signals.moved.dispatch(dx, dy) if (this.pressed) { this.signals.dragged.dispatch(dx, dy) - this.signals.draggedXY.dispatch( - this.position.x, - this.position.y - ) } break } @@ -440,12 +434,6 @@ class MouseObserver { this.signals.moved.dispatch(dx, dy) if (this.pressed) { this.signals.dragged.dispatch(dx, dy) - this.signals.draggedXY.dispatch( - this.prevPosition.x, - this.prevPosition.y, - this.position.x, - this.position.y - ) } } } From ed230c79cdb5c03e075c885546e002fdc65c2ecc Mon Sep 17 00:00:00 2001 From: Lily Wang Date: Tue, 18 Jun 2019 15:23:31 +1000 Subject: [PATCH 14/16] removed autoformatting --- src/component/structure-component.ts | 58 +++++------ src/controls/mouse-actions.ts | 116 ++++++++++----------- src/controls/mouse-controls.ts | 5 +- src/controls/picking-controls.ts | 8 +- src/stage/mouse-observer.ts | 80 +++++++-------- src/stage/picking-behavior.ts | 8 +- src/stage/stage.ts | 102 ++++++++++--------- src/structure/structure.ts | 144 +++++++++++++-------------- src/ui/parameters.ts | 14 +-- src/viewer/viewer.ts | 140 +++++++++++++------------- 10 files changed, 335 insertions(+), 340 deletions(-) diff --git a/src/component/structure-component.ts b/src/component/structure-component.ts index 74781cea9..a4da13abf 100644 --- a/src/component/structure-component.ts +++ b/src/component/structure-component.ts @@ -28,9 +28,9 @@ import { Vector3, Box3 } from 'three'; import { createToggleSet, ToggleSet } from '../utils/toggle-set'; export type StructureRepresentationType = ( - 'angle' | 'axes' | 'backbone' | 'ball+stick' | 'base' | 'cartoon' | 'contact' | 'dihedral' | - 'distance' | 'helixorient' | 'hyperball' | 'label' | 'licorice' | 'line' | 'surface' | - 'ribbon' | 'rocket' | 'rope' | 'selected' | 'spacefill' | 'trace' | 'tube' | 'unitcell' | 'selected' + 'angle'|'axes'|'backbone'|'ball+stick'|'base'|'cartoon'|'contact'|'dihedral' | + 'distance'|'helixorient'|'hyperball'|'label'|'licorice'|'line'|'surface' | + 'ribbon'|'rocket'|'rope'|'selected'|'spacefill'|'trace'|'tube'|'unitcell'|'selected' ) export const StructureComponentDefaultParameters = Object.assign({ @@ -58,7 +58,7 @@ export interface StructureComponentSignals extends ComponentSignals { class StructureComponent extends Component { readonly signals: StructureComponentSignals readonly parameters: StructureComponentParameters - get defaultParameters() { return StructureComponentDefaultParameters } + get defaultParameters () { return StructureComponentDefaultParameters } selection: Selection structureView: StructureView @@ -77,7 +77,7 @@ class StructureComponent extends Component { measureRepresentations: RepresentationCollection - constructor(stage: Stage, readonly structure: Structure, params: Partial = {}) { + constructor (stage: Stage, readonly structure: Structure, params: Partial = {}) { super(stage, structure, Object.assign({ name: structure.name }, params)) this.signals = Object.assign(this.signals, { @@ -137,7 +137,7 @@ class StructureComponent extends Component { * Component type * @type {String} */ - get type() { return 'structure' } + get type () { return 'structure' } /** * Initialize selection @@ -145,7 +145,7 @@ class StructureComponent extends Component { * @param {String} sele - selection string * @return {undefined} */ - initSelection(sele: string) { + initSelection (sele: string) { /** * Selection for {@link StructureComponent#structureView} * @private @@ -175,7 +175,7 @@ class StructureComponent extends Component { * @param {String} string - selection string * @return {StructureComponent} this object */ - setSelection(string: string) { + setSelection (string: string) { this.parameters.sele = string this.selection.setString(string) return this @@ -186,7 +186,7 @@ class StructureComponent extends Component { * @param {String} value - assembly name * @return {undefined} */ - setDefaultAssembly(value: string) { + setDefaultAssembly (value: string) { // filter out non-existing assemblies if (this.structure.biomolDict[value] === undefined) value = '' // only set default assembly when changed @@ -205,7 +205,7 @@ class StructureComponent extends Component { * Rebuild all representations * @return {undefined} */ - rebuildRepresentations() { + rebuildRepresentations () { this.reprList.forEach((repr: RepresentationElement) => { repr.build() }) @@ -217,19 +217,19 @@ class StructureComponent extends Component { * Rebuild all trajectories * @return {undefined} */ - rebuildTrajectories() { + rebuildTrajectories () { this.trajList.forEach(trajComp => { trajComp.trajectory.setStructure(this.structureView) }) } - updateRepresentations(what: any) { + updateRepresentations (what: any) { super.updateRepresentations(what) this.measureRepresentations.update(what) this.selectedRepresentation.update(what) } - addRepresentation(type: StructureRepresentationType, params: { [k: string]: any } = {}, hidden = false) { + addRepresentation (type: StructureRepresentationType, params: { [k: string]: any } = {}, hidden = false) { params.defaultAssembly = this.parameters.defaultAssembly const reprComp = this._addRepresentation(type, this.structureView, params, hidden) @@ -242,7 +242,7 @@ class StructureComponent extends Component { /** * Add a new trajectory component to the structure */ - addTrajectory(trajPath = '', params: { [k: string]: any } = {}) { + addTrajectory (trajPath = '', params: { [k: string]: any } = {}) { const traj = makeTrajectory(trajPath, this.structureView, params as TrajectoryParameters) traj.signals.frameChanged.add(() => { @@ -256,7 +256,7 @@ class StructureComponent extends Component { return trajComp } - removeTrajectory(traj: TrajectoryElement) { + removeTrajectory (traj: TrajectoryElement) { const idx = this.trajList.indexOf(traj) if (idx !== -1) { this.trajList.splice(idx, 1) @@ -267,7 +267,7 @@ class StructureComponent extends Component { this.signals.trajectoryRemoved.dispatch(traj) } - dispose() { + dispose () { // copy via .slice because side effects may change trajList this.trajList.slice().forEach(traj => traj.dispose()) @@ -285,8 +285,8 @@ class StructureComponent extends Component { * @param {Integer} [duration] - duration of the animation, defaults to 0 * @return {undefined} */ - autoView(duration?: number): any - autoView(sele?: string | number, duration?: number) { + autoView (duration?: number): any + autoView (sele?: string|number, duration?: number) { if (typeof sele === 'number') { duration = sele sele = '' @@ -299,7 +299,7 @@ class StructureComponent extends Component { ) } - getBoxUntransformed(sele: string): Box3 { + getBoxUntransformed (sele: string): Box3 { let bb if (sele) { @@ -311,7 +311,7 @@ class StructureComponent extends Component { return bb } - getCenterUntransformed(sele: string): Vector3 { + getCenterUntransformed (sele: string): Vector3 { if (sele && typeof sele === 'string') { return this.structure.atomCenter(new Selection(sele)) } else { @@ -319,7 +319,7 @@ class StructureComponent extends Component { } } - superpose(component: StructureComponent, align: boolean, sele1: string, sele2: string) { + superpose (component: StructureComponent, align: boolean, sele1: string, sele2: string) { superpose( this.structureView, component.structureView, align, sele1, sele2 ) @@ -329,7 +329,7 @@ class StructureComponent extends Component { return this } - getMaxRepresentationRadius(atomIndex: number) { + getMaxRepresentationRadius (atomIndex: number) { let maxRadius = 0 const atom = this.structure.getAtomProxy(atomIndex) this.eachRepresentation(reprElem => { @@ -341,7 +341,7 @@ class StructureComponent extends Component { return maxRadius } - measurePick(atom: AtomProxy) { + measurePick (atom: AtomProxy) { const pickCount = this.pickBuffer.count if (this.lastPick === atom.index && pickCount >= 1) { @@ -379,20 +379,20 @@ class StructureComponent extends Component { this.measureUpdate() } - measureClear() { + measureClear () { this.pickBuffer.clear() this.lastPick = undefined this.spacefillRepresentation.setSelection('none') } - measureBuild() { + measureBuild () { const md = this.measureData() this.distanceRepresentation.setParameters({ atomPair: md.distance }) this.angleRepresentation.setParameters({ atomTriple: md.angle }) this.dihedralRepresentation.setParameters({ atomQuad: md.dihedral }) } - measureUpdate() { + measureUpdate () { const pickData = this.pickBuffer.data const radiusData: { [k: number]: number } = {} pickData.forEach(ai => { @@ -405,7 +405,7 @@ class StructureComponent extends Component { this.spacefillRepresentation.setParameters({ radiusData }) } - measureData() { + measureData () { const pv = this.pickDict.values return { distance: pv.filter(l => l.length === 2), @@ -417,7 +417,7 @@ class StructureComponent extends Component { /** * Remove all measurements, optionally limit to distance, angle or dihedral */ - removeAllMeasurements(type?: MeasurementFlags) { + removeAllMeasurements (type?: MeasurementFlags) { const pd = this.pickDict const pv = pd.values const remove = function (len: number) { @@ -432,7 +432,7 @@ class StructureComponent extends Component { /** * Remove a measurement given as a pair, triple, quad of atom indices */ - removeMeasurement(atomList: number[]) { + removeMeasurement (atomList: number[]) { this.pickDict.del(atomList.slice().sort()) this.measureBuild() } diff --git a/src/controls/mouse-actions.ts b/src/controls/mouse-actions.ts index c3c2d9171..a085e83e4 100644 --- a/src/controls/mouse-actions.ts +++ b/src/controls/mouse-actions.ts @@ -25,7 +25,7 @@ class MouseActions { * @param {Number} delta - amount to zoom * @return {undefined} */ - static zoomScroll(stage: Stage, delta: number) { + static zoomScroll (stage: Stage, delta: number) { stage.trackballControls.zoom(delta) } @@ -35,7 +35,7 @@ class MouseActions { * @param {Number} delta - amount to move clipping plane * @return {undefined} */ - static clipNearScroll(stage: Stage, delta: number) { + static clipNearScroll (stage: Stage, delta: number) { const sp = stage.getParameters() stage.setParameters({ clipNear: sp.clipNear + delta / 10 }) } @@ -46,7 +46,7 @@ class MouseActions { * @param {Number} delta - amount to move focus planes * @return {undefined} */ - static focusScroll(stage: Stage, delta: number) { + static focusScroll (stage: Stage, delta: number) { const sp = stage.getParameters() const focus = sp.clipNear * 2 const sign = Math.sign(delta) @@ -61,7 +61,7 @@ class MouseActions { * @param {Number} delta - amount to move focus planes and zoom * @return {undefined} */ - static zoomFocusScroll(stage: Stage, delta: number) { + static zoomFocusScroll (stage: Stage, delta: number) { stage.trackballControls.zoom(delta) const z = stage.viewer.camera.position.z stage.setFocus(100 - Math.abs(z / 8)) @@ -73,7 +73,7 @@ class MouseActions { * @param {Number} delta - amount to change isolevel * @return {undefined} */ - static isolevelScroll(stage: Stage, delta: number) { + static isolevelScroll (stage: Stage, delta: number) { const d = Math.sign(delta) / 10 stage.eachRepresentation((reprElem, comp) => { if (reprElem.repr instanceof SurfaceRepresentation) { @@ -92,7 +92,7 @@ class MouseActions { * @param {Number} dy - amount to pan in y direction * @return {undefined} */ - static panDrag(stage: Stage, dx: number, dy: number) { + static panDrag (stage: Stage, dx: number, dy: number) { stage.trackballControls.pan(dx, dy) } @@ -103,7 +103,7 @@ class MouseActions { * @param {Number} dy - amount to rotate in y direction * @return {undefined} */ - static rotateDrag(stage: Stage, dx: number, dy: number) { + static rotateDrag (stage: Stage, dx: number, dy: number) { stage.trackballControls.rotate(dx, dy) } @@ -114,7 +114,7 @@ class MouseActions { * @param {Number} dy - amount to rotate in y direction * @return {undefined} */ - static zRotateDrag(stage: Stage, dx: number, dy: number) { + static zRotateDrag (stage: Stage, dx: number, dy: number) { stage.trackballControls.zRotate(dx, dy) } @@ -125,7 +125,7 @@ class MouseActions { * @param {Number} dy - amount to zoom * @return {undefined} */ - static zoomDrag(stage: Stage, dx: number, dy: number) { + static zoomDrag (stage: Stage, dx: number, dy: number) { stage.trackballControls.zoom((dx + dy) / -2) } @@ -137,7 +137,7 @@ class MouseActions { * @param {Number} dy - amount to zoom and focus * @return {undefined} */ - static zoomFocusDrag(stage: Stage, dx: number, dy: number) { + static zoomFocusDrag (stage: Stage, dx: number, dy: number) { stage.trackballControls.zoom((dx + dy) / -2) const z = stage.viewer.camera.position.z stage.setFocus(100 - Math.abs(z / 8)) @@ -150,7 +150,7 @@ class MouseActions { * @param {Number} dy - amount to pan in y direction * @return {undefined} */ - static panComponentDrag(stage: Stage, dx: number, dy: number) { + static panComponentDrag (stage: Stage, dx: number, dy: number) { stage.trackballControls.panComponent(dx, dy) } @@ -161,7 +161,7 @@ class MouseActions { * @param {Number} dy - amount to pan in y direction * @return {undefined} */ - static panAtomDrag(stage: Stage, dx: number, dy: number) { + static panAtomDrag (stage: Stage, dx: number, dy: number) { stage.trackballControls.panAtom(dx, dy) } @@ -172,7 +172,7 @@ class MouseActions { * @param {Number} dy - amount to rotate in y direction * @return {undefined} */ - static rotateComponentDrag(stage: Stage, dx: number, dy: number) { + static rotateComponentDrag (stage: Stage, dx: number, dy: number) { stage.trackballControls.rotateComponent(dx, dy) } @@ -183,7 +183,7 @@ class MouseActions { * @param {Number} dy - amount to move in y direction * @return {undefined} */ - static moveComponentDrag(stage: Stage, dx: number, dy: number) { + static moveComponentDrag (stage: Stage, dx: number, dy: number) { stage.trackballControls.translateAtoms(dx, dy) } @@ -195,7 +195,7 @@ class MouseActions { * @param {Number} dy - amount to move in y direction * @return {undefined} */ - static rotateSelectionDrag(stage: Stage, dx: number, dy: number) { + static rotateSelectionDrag (stage: Stage, dx: number, dy: number) { stage.trackballControls.rotateAtoms(dx, dy) } @@ -205,7 +205,7 @@ class MouseActions { * @param {PickingProxy} pickingProxy - the picking data object * @return {undefined} */ - static movePick(stage: Stage, pickingProxy: PickingProxy) { + static movePick (stage: Stage, pickingProxy: PickingProxy) { if (pickingProxy) { stage.animationControls.move(pickingProxy.position.clone()) } @@ -217,7 +217,7 @@ class MouseActions { * @param {PickingProxy} pickingProxy - the picking data object * @return {undefined} */ - static tooltipPick(stage: Stage, pickingProxy: PickingProxy) { + static tooltipPick (stage: Stage, pickingProxy: PickingProxy) { const tt = stage.tooltip const sp = stage.getParameters() as any if (sp.tooltip && pickingProxy) { @@ -232,7 +232,7 @@ class MouseActions { } - static measurePick(stage: Stage, pickingProxy: PickingProxy) { + static measurePick (stage: Stage, pickingProxy: PickingProxy) { if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) { const atom = pickingProxy.atom || pickingProxy.closestBondAtom const sc = pickingProxy.component as StructureComponent @@ -248,7 +248,7 @@ class MouseActions { * @param {PickingProxy} pickingProxy - the picking data object * @return {undefined} */ - static selectPick(stage: Stage, pickingProxy: PickingProxy) { + static selectPick (stage: Stage, pickingProxy: PickingProxy) { if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) { const atoms = [pickingProxy.atom.index] || [pickingProxy.bond.atom1.index, pickingProxy.bond.atom2.index] const sc = pickingProxy.component as StructureComponent @@ -256,7 +256,7 @@ class MouseActions { } } - static clearSelect(stage: Stage) { + static clearSelect (stage: Stage) { stage.eachComponent(function (sc: StructureComponent) { sc.selectedAtomIndices.clear() sc.selectedUpdate() @@ -267,56 +267,56 @@ class MouseActions { type MouseActionPreset = [string, MouseActionCallback][] export const MouseActionPresets = { default: [ - ['scroll', MouseActions.zoomScroll], - ['scroll-shift', MouseActions.focusScroll], - ['scroll-ctrl', MouseActions.isolevelScroll], - ['scroll-shift-ctrl', MouseActions.zoomFocusScroll], + [ 'scroll', MouseActions.zoomScroll ], + [ 'scroll-shift', MouseActions.focusScroll ], + [ 'scroll-ctrl', MouseActions.isolevelScroll ], + [ 'scroll-shift-ctrl', MouseActions.zoomFocusScroll ], - ['drag-left', MouseActions.rotateDrag], - ['drag-right', MouseActions.panDrag], - ['drag-ctrl-left', MouseActions.panDrag], - ['drag-ctrl-right', MouseActions.zRotateDrag], - ['drag-shift-right', MouseActions.moveComponentDrag], - ['drag-shift-left', MouseActions.zoomDrag], - ['drag-middle', MouseActions.zoomFocusDrag], + [ 'drag-left', MouseActions.rotateDrag ], + [ 'drag-right', MouseActions.panDrag ], + [ 'drag-ctrl-left', MouseActions.panDrag ], + [ 'drag-ctrl-right', MouseActions.zRotateDrag ], + [ 'drag-shift-right', MouseActions.moveComponentDrag ], + [ 'drag-shift-left', MouseActions.zoomDrag ], + [ 'drag-middle', MouseActions.zoomFocusDrag ], - ['clickPick-shift-left', MouseActions.selectPick], - ['doubleClick-shift-left', MouseActions.clearSelect], + [ 'clickPick-shift-left', MouseActions.selectPick ], + [ 'doubleClick-shift-left', MouseActions.clearSelect ], - ['clickPick-right', MouseActions.measurePick], - ['clickPick-ctrl-left', MouseActions.measurePick], - ['clickPick-middle', MouseActions.movePick], - ['clickPick-left', MouseActions.movePick], - ['hoverPick', MouseActions.tooltipPick] + [ 'clickPick-right', MouseActions.measurePick ], + [ 'clickPick-ctrl-left', MouseActions.measurePick ], + [ 'clickPick-middle', MouseActions.movePick ], + [ 'clickPick-left', MouseActions.movePick ], + [ 'hoverPick', MouseActions.tooltipPick] ] as MouseActionPreset, pymol: [ - ['drag-left', MouseActions.rotateDrag], - ['drag-middle', MouseActions.panDrag], - ['drag-right', MouseActions.zoomDrag], - ['drag-shift-right', MouseActions.focusScroll], + [ 'drag-left', MouseActions.rotateDrag ], + [ 'drag-middle', MouseActions.panDrag ], + [ 'drag-right', MouseActions.zoomDrag ], + [ 'drag-shift-right', MouseActions.focusScroll ], - ['clickPick-ctrl+shift-middle', MouseActions.movePick], - ['hoverPick', MouseActions.tooltipPick] + [ 'clickPick-ctrl+shift-middle', MouseActions.movePick ], + [ 'hoverPick', MouseActions.tooltipPick] ] as MouseActionPreset, coot: [ - ['scroll', MouseActions.isolevelScroll], + [ 'scroll', MouseActions.isolevelScroll ], - ['drag-left', MouseActions.rotateDrag], - ['drag-middle', MouseActions.panDrag], - ['drag-ctrl-left', MouseActions.panDrag], - ['drag-right', MouseActions.zoomFocusDrag], - ['drag-ctrl-right', MouseActions.focusScroll], + [ 'drag-left', MouseActions.rotateDrag ], + [ 'drag-middle', MouseActions.panDrag ], + [ 'drag-ctrl-left', MouseActions.panDrag ], + [ 'drag-right', MouseActions.zoomFocusDrag ], + [ 'drag-ctrl-right', MouseActions.focusScroll ], - ['clickPick-middle', MouseActions.movePick], - ['hoverPick', MouseActions.tooltipPick] + [ 'clickPick-middle', MouseActions.movePick ], + [ 'hoverPick', MouseActions.tooltipPick] ] as MouseActionPreset, astexviewer: [ - ['drag-left', MouseActions.rotateDrag], - ['drag-ctrl-left', MouseActions.panDrag], - ['drag-shift-left', MouseActions.zoomDrag], - ['scroll', MouseActions.focusScroll], - ['clickPick-middle', MouseActions.movePick], - ['hoverPick', MouseActions.tooltipPick] + [ 'drag-left', MouseActions.rotateDrag ], + [ 'drag-ctrl-left', MouseActions.panDrag ], + [ 'drag-shift-left', MouseActions.zoomDrag ], + [ 'scroll', MouseActions.focusScroll ], + [ 'clickPick-middle', MouseActions.movePick ], + [ 'hoverPick', MouseActions.tooltipPick] ] as MouseActionPreset } diff --git a/src/controls/mouse-controls.ts b/src/controls/mouse-controls.ts index 8a077b45f..7340bb838 100644 --- a/src/controls/mouse-controls.ts +++ b/src/controls/mouse-controls.ts @@ -14,7 +14,7 @@ export interface MouseControlsParams { disabled?: boolean } -export type MouseActionType = ''|'scroll'|'drag'|'click'|'doubleClick'|'hover'|'clickPick'|'hoverPick'|'dragXY'|'press'|'drop' +export type MouseActionType = ''|'scroll'|'drag'|'click'|'doubleClick'|'hover'|'clickPick'|'hoverPick' export interface MouseAction { type: MouseActionType key: number @@ -62,14 +62,11 @@ function triggerFromString (str: string) { let type = '' if (tokens.includes('scroll')) type = 'scroll' if (tokens.includes('drag')) type = 'drag' - if (tokens.includes('dragXY')) type = 'dragXY' if (tokens.includes('click')) type = 'click' if (tokens.includes('doubleClick')) type = 'doubleClick' if (tokens.includes('hover')) type = 'hover' if (tokens.includes('clickPick')) type = 'clickPick' if (tokens.includes('hoverPick')) type = 'hoverPick' - if (tokens.includes('press')) type = 'press' - if (tokens.includes('drop')) type = 'drop' let key = 0 if (tokens.includes('alt')) key += 1 diff --git a/src/controls/picking-controls.ts b/src/controls/picking-controls.ts index 415edb097..bccf4423d 100644 --- a/src/controls/picking-controls.ts +++ b/src/controls/picking-controls.ts @@ -14,7 +14,7 @@ import Viewer from '../viewer/viewer' class PickingControls { viewer: Viewer - constructor(readonly stage: Stage) { + constructor (readonly stage: Stage) { this.viewer = stage.viewer } @@ -24,12 +24,12 @@ class PickingControls { * @param {Number} y - canvas y coordinate * @return {PickingProxy|undefined} picking proxy */ - pick(x: number, y: number) { + pick (x: number, y: number) { const pickingData = this.viewer.pick(x, y) if (pickingData.picker && - pickingData.picker.type !== 'ignore' && - pickingData.pid !== undefined + pickingData.picker.type !== 'ignore' && + pickingData.pid !== undefined ) { const pickerArray = pickingData.picker.array if (pickerArray && pickingData.pid >= pickerArray.length) { diff --git a/src/stage/mouse-observer.ts b/src/stage/mouse-observer.ts index a58d3929c..6891830a4 100644 --- a/src/stage/mouse-observer.ts +++ b/src/stage/mouse-observer.ts @@ -25,13 +25,13 @@ import MouseControls from '../controls/mouse-controls' * @property {Signal} hovered - on hover */ -function getTouchDistance(event: TouchEvent) { - const dx = event.touches[0].pageX - event.touches[1].pageX - const dy = event.touches[0].pageY - event.touches[1].pageY +function getTouchDistance (event: TouchEvent) { + const dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX + const dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY return Math.sqrt(dx * dx + dy * dy) } -function getMouseButtons(event: MouseEvent) { +function getMouseButtons (event: MouseEvent) { if (typeof event === 'object') { if ('buttons' in event) { return event.buttons @@ -65,7 +65,7 @@ export interface MouseSignals { dropped: Signal // on drop clicked: Signal // on click hovered: Signal // on hover - doubleClicked: Signal // on double click + doubleClicked: Signal } export interface MouseParams { @@ -109,7 +109,7 @@ class MouseObserver { dropped: new Signal(), clicked: new Signal(), hovered: new Signal(), - doubleClicked: new Signal(), + doubleClicked: new Signal() } hoverTimeout: number @@ -130,9 +130,9 @@ class MouseObserver { hovering = true // Flag indicating if the mouse is hovering scrolled = false // Flag indicating if there was a scolling event since the last mouse move lastMoved = Infinity // Timestamp of last mouse move - which?= 0 // 0: No button; 1: Left button; 2: Middle button; 3: Right button - buttons?= 0 // 0: No button; 1: Left button; 2: Right button; 4: Middle button - pressed?= false // Flag indicating if the mouse is pressed down + which? = 0 // 0: No button; 1: Left button; 2: Middle button; 3: Right button + buttons? = 0 // 0: No button; 1: Left button; 2: Right button; 4: Middle button + pressed? = false // Flag indicating if the mouse is pressed down altKey = false // Flag indicating if the alt key is pressed ctrlKey = false // Flag indicating if the ctrl key is pressed metaKey = false // Flag indicating if the meta key is pressed @@ -151,7 +151,7 @@ class MouseObserver { * @param {Boolean} params.handleScroll - whether or not to handle scroll events * @param {Integer} params.doubleClickSpeed - max time in ms to trigger double click */ - constructor(readonly domElement: HTMLCanvasElement, params: MouseParams = {}) { + constructor (readonly domElement: HTMLCanvasElement, params: MouseParams = {}) { this.domElement.style.touchAction = 'none' this.hoverTimeout = defaults(params.hoverTimeout, 50) @@ -183,7 +183,7 @@ class MouseObserver { document.addEventListener('touchmove', this._onTouchmove, opt) } - get key() { + get key () { let key = 0 if (this.altKey) key += 1 if (this.ctrlKey) key += 2 @@ -192,7 +192,7 @@ class MouseObserver { return key } - setParameters(params: MouseParams = {}) { + setParameters (params: MouseParams = {}) { this.hoverTimeout = defaults(params.hoverTimeout, this.hoverTimeout) } @@ -202,7 +202,7 @@ class MouseObserver { * @emits {MouseSignals.hovered} when hovered * @return {undefined} */ - _listen() { + _listen () { const now = window.performance.now() const cp = this.canvasPosition if (this.doubleClickPending && now - this.lastClicked > this.doubleClickSpeed) { @@ -227,7 +227,7 @@ class MouseObserver { * @param {Event} event - mouse event * @return {undefined} */ - _onMousewheel(event: MouseWheelEvent) { + _onMousewheel (event: MouseWheelEvent) { if (event.target !== this.domElement || !this.handleScroll) { return } @@ -260,7 +260,7 @@ class MouseObserver { * @param {Event} event - mouse event * @return {undefined} */ - _onMousemove(event: MouseEvent) { + _onMousemove (event: MouseEvent) { if (event.target === this.domElement) { event.preventDefault() this.overElement = true @@ -282,7 +282,7 @@ class MouseObserver { } } - _onMousedown(event: MouseEvent) { + _onMousedown (event: MouseEvent) { if (event.target !== this.domElement) { return } @@ -305,7 +305,7 @@ class MouseObserver { * @param {Event} event - mouse event * @return {undefined} */ - _onMouseup(event: MouseEvent) { + _onMouseup (event: MouseEvent) { if (event.target === this.domElement) { event.preventDefault() } @@ -330,13 +330,13 @@ class MouseObserver { // } } - _onContextmenu(event: MouseEvent) { + _onContextmenu (event: MouseEvent) { if (event.target === this.domElement) { event.preventDefault() } } - _onTouchstart(event: TouchEvent) { + _onTouchstart (event: TouchEvent) { if (event.target !== this.domElement) { return } @@ -347,32 +347,32 @@ class MouseObserver { this.moving = false this.hovering = false this.down.set( - event.touches[0].pageX, - event.touches[0].pageY + event.touches[ 0 ].pageX, + event.touches[ 0 ].pageY ) this.position.set( - event.touches[0].pageX, - event.touches[0].pageY + event.touches[ 0 ].pageX, + event.touches[ 0 ].pageY ) - this._setCanvasPosition(event.touches[0]) + this._setCanvasPosition(event.touches[ 0 ]) break } case 2: { this.down.set( - (event.touches[0].pageX + event.touches[1].pageX) / 2, - (event.touches[0].pageY + event.touches[1].pageY) / 2 + (event.touches[ 0 ].pageX + event.touches[ 1 ].pageX) / 2, + (event.touches[ 0 ].pageY + event.touches[ 1 ].pageY) / 2 ) this.position.set( - (event.touches[0].pageX + event.touches[1].pageX) / 2, - (event.touches[0].pageY + event.touches[1].pageY) / 2 + (event.touches[ 0 ].pageX + event.touches[ 1 ].pageX) / 2, + (event.touches[ 0 ].pageY + event.touches[ 1 ].pageY) / 2 ) this.lastTouchDistance = getTouchDistance(event) } } } - _onTouchend(event: TouchEvent) { + _onTouchend (event: TouchEvent) { if (event.target === this.domElement) { event.preventDefault() } @@ -381,7 +381,7 @@ class MouseObserver { this.pressed = undefined } - _onTouchmove(event: TouchEvent) { + _onTouchmove (event: TouchEvent) { if (event.target === this.domElement) { event.preventDefault() this.overElement = true @@ -398,10 +398,10 @@ class MouseObserver { this.lastMoved = window.performance.now() this.prevPosition.copy(this.position) this.position.set( - event.touches[0].pageX, - event.touches[0].pageY + event.touches[ 0 ].pageX, + event.touches[ 0 ].pageY ) - this._setCanvasPosition(event.touches[0]) + this._setCanvasPosition(event.touches[ 0 ]) const dx = this.prevPosition.x - this.position.x const dy = this.prevPosition.y - this.position.y this.signals.moved.dispatch(dx, dy) @@ -417,11 +417,11 @@ class MouseObserver { this.lastTouchDistance = touchDistance this.prevPosition.copy(this.position) this.position.set( - (event.touches[0].pageX + event.touches[1].pageX) / 2, - (event.touches[0].pageY + event.touches[1].pageY) / 2 + (event.touches[ 0 ].pageX + event.touches[ 1 ].pageX) / 2, + (event.touches[ 0 ].pageY + event.touches[ 1 ].pageY) / 2 ) if (Math.abs(delta) > 2 && this.handleScroll && - this.position.distanceTo(this.prevPosition) < 2 + this.position.distanceTo(this.prevPosition) < 2 ) { this.which = 0 this.buttons = 0 @@ -440,11 +440,11 @@ class MouseObserver { } } - _distance() { + _distance () { return this.position.distanceTo(this.down) } - _setCanvasPosition(event: any) { // TODO + _setCanvasPosition (event: any) { // TODO const box = this.domElement.getBoundingClientRect() let offsetX, offsetY if ('offsetX' in event && 'offsetY' in event) { @@ -457,14 +457,14 @@ class MouseObserver { this.canvasPosition.set(offsetX, box.height - offsetY) } - _setKeys(event: MouseEvent | TouchEvent) { + _setKeys (event: MouseEvent|TouchEvent) { this.altKey = event.altKey this.ctrlKey = event.ctrlKey this.metaKey = event.metaKey this.shiftKey = event.shiftKey } - dispose() { + dispose () { document.removeEventListener('mousewheel', this._onMousewheel) document.removeEventListener('wheel', this._onMousewheel) document.removeEventListener('MozMousePixelScroll', this._onMousewheel) diff --git a/src/stage/picking-behavior.ts b/src/stage/picking-behavior.ts index f157f04fe..a92c44e3d 100644 --- a/src/stage/picking-behavior.ts +++ b/src/stage/picking-behavior.ts @@ -14,7 +14,7 @@ class PickingBehavior { mouse: MouseObserver controls: MouseControls - constructor(readonly stage: Stage) { + constructor (readonly stage: Stage) { this.stage = stage this.mouse = stage.mouseObserver this.controls = stage.mouseControls @@ -23,13 +23,13 @@ class PickingBehavior { this.mouse.signals.hovered.add(this._onHover, this) } - _onClick(x: number, y: number) { + _onClick (x: number, y: number) { const pickingProxy = this.stage.pickingControls.pick(x, y) this.stage.signals.clicked.dispatch(pickingProxy) this.controls.run('clickPick', pickingProxy) } - _onHover(x: number, y: number) { + _onHover (x: number, y: number) { const pickingProxy = this.stage.pickingControls.pick(x, y) if (pickingProxy && this.mouse.down.equals(this.mouse.position)) { this.stage.transformComponent = pickingProxy.component @@ -39,7 +39,7 @@ class PickingBehavior { this.controls.run('hoverPick', pickingProxy) } - dispose() { + dispose () { this.mouse.signals.clicked.remove(this._onClick, this) this.mouse.signals.hovered.remove(this._onHover, this) } diff --git a/src/stage/stage.ts b/src/stage/stage.ts index 0b57c28be..b45f79ed2 100644 --- a/src/stage/stage.ts +++ b/src/stage/stage.ts @@ -47,7 +47,7 @@ import Volume from '../surface/volume' import Shape from '../geometry/shape' import Script from '../script' -function matchName(name: string | RegExp, object: { name: string }) { +function matchName (name: string|RegExp, object: { name: string }) { if (name instanceof RegExp) { return object.name.match(name) !== null } else { @@ -113,14 +113,14 @@ export interface StageSignals { hovered: Signal } -export type RenderQualityType = 'auto' | 'low' | 'medium' | 'high' +export type RenderQualityType = 'auto'|'low'|'medium'|'high' export const StageDefaultParameters = { impostor: true, quality: 'medium' as RenderQualityType, workerDefault: true, sampleLevel: 0, - backgroundColor: 'black' as string | number, + backgroundColor: 'black' as string|number, rotateSpeed: 2.0, zoomSpeed: 1.2, panSpeed: 1.0, @@ -131,10 +131,10 @@ export const StageDefaultParameters = { fogFar: 100, cameraFov: 40, cameraEyeSep: 0.3, - cameraType: 'perspective' as 'perspective' | 'orthographic' | 'stereo', - lightColor: 0xdddddd as string | number, + cameraType: 'perspective' as 'perspective'|'orthographic'|'stereo', + lightColor: 0xdddddd as string|number, lightIntensity: 1.0, - ambientColor: 0xdddddd as string | number, + ambientColor: 0xdddddd as string|number, ambientIntensity: 0.2, hoverTimeout: 0, tooltip: true, @@ -195,7 +195,7 @@ class Stage { spinAnimation: Animation rockAnimation: Animation - constructor(idOrElement: string | HTMLElement, params: Partial = {}) { + constructor (idOrElement: string|HTMLElement, params: Partial = {}) { this.viewer = new Viewer(idOrElement) if (!this.viewer.renderer) return @@ -212,7 +212,6 @@ class Stage { }) this.viewer.container.appendChild(this.tooltip) - this.mouseObserver = new MouseObserver(this.viewer.renderer.domElement) this.viewerControls = new ViewerControls(this) this.trackballControls = new TrackballControls(this) @@ -226,9 +225,9 @@ class Stage { this.animationBehavior = new AnimationBehavior(this) this.keyBehavior = new KeyBehavior(this) - this.spinAnimation = this.animationControls.spin([0, 1, 0], 0.005) + this.spinAnimation = this.animationControls.spin([ 0, 1, 0 ], 0.005) this.spinAnimation.pause(true) - this.rockAnimation = this.animationControls.rock([0, 1, 0], 0.005) + this.rockAnimation = this.animationControls.rock([ 0, 1, 0 ], 0.005) this.rockAnimation.pause(true) // must come after the viewer has been instantiated @@ -241,7 +240,7 @@ class Stage { /** * Set stage parameters */ - setParameters(params: Partial = {}) { + setParameters (params: Partial = {}) { updateParams(this.parameters, params) const p = params @@ -270,7 +269,7 @@ class Stage { return this } - log(msg: string) { + log (msg: string) { console.log('STAGE LOG', msg) this.logList.push(msg) } @@ -278,7 +277,7 @@ class Stage { /** * Get stage parameters */ - getParameters() { + getParameters () { return Object.assign({}, this.parameters) } @@ -287,7 +286,7 @@ class Stage { * @param {StructureComponent|SurfaceComponent} object - component to create the representations for * @return {undefined} */ - defaultFileRepresentation(component: Component) { + defaultFileRepresentation (component: Component) { if (component instanceof StructureComponent) { component.setSelection('/0') @@ -445,14 +444,14 @@ class Stage { * a {@link SurfaceComponent} or a {@link ScriptComponent} object, * depending on the type of the loaded file. */ - loadFile(path: string | File | Blob, params: Partial = {}) { + loadFile (path: string|File|Blob, params: Partial = {}) { const p = Object.assign({}, this.defaultFileParams, params) const name = getFileInfo(path).name this.tasks.increment() this.log(`loading file '${name}'`) - const onLoadFn = (object: Structure | Surface | Volume) => { + const onLoadFn = (object: Structure|Surface|Volume) => { this.log(`loaded '${name}'`) const component = this.addComponentFromObject(object, p) @@ -464,7 +463,7 @@ class Stage { return component } - const onErrorFn = (e: Error | string) => { + const onErrorFn = (e: Error|string) => { this.tasks.decrement() const errorMsg = `error loading file: '${e}'` this.log(errorMsg) @@ -485,7 +484,7 @@ class Stage { return promise.then(onLoadFn, onErrorFn) } - loadScript(path: string | File | Blob) { + loadScript (path: string|File|Blob) { const name = getFileInfo(path).name this.log(`loading script '${name}'`) @@ -500,7 +499,7 @@ class Stage { }) this.log(`called script '${name}'`) }, - (error: Error | string) => { + (error: Error|string) => { this.tasks.decrement() const errorMsg = `errored script '${name}' "${error}"` this.log(errorMsg) @@ -514,7 +513,7 @@ class Stage { * @param {Component} component - the component to add * @return {undefined} */ - addComponent(component: Component) { + addComponent (component: Component) { if (!component) { Log.warn('Stage.addComponent: no component given') return @@ -527,7 +526,7 @@ class Stage { /** * Create a component from the given object and add to the stage */ - addComponentFromObject(object: Structure | Surface | Volume | Shape, params: Partial = {}) { + addComponentFromObject (object: Structure|Surface|Volume|Shape, params: Partial = {}) { const CompClass = ComponentRegistry.get(object.type) if (CompClass) { @@ -544,7 +543,7 @@ class Stage { * @param {Component} component - the component to remove * @return {undefined} */ - removeComponent(component: Component) { + removeComponent (component: Component) { const idx = this.compList.indexOf(component) if (idx !== -1) { this.compList.splice(idx, 1) @@ -556,7 +555,7 @@ class Stage { /** * Remove all components from the stage */ - removeAllComponents() { + removeAllComponents () { this.compList.slice().forEach(o => this.removeComponent(o)) } @@ -564,7 +563,7 @@ class Stage { * Handle any size-changes of the container element * @return {undefined} */ - handleResize() { + handleResize () { this.viewer.handleResize() } @@ -574,7 +573,7 @@ class Stage { * @param {String} height - CSS height value * @return {undefined} */ - setSize(width: string, height: string) { + setSize (width: string, height: string) { const container = this.viewer.container if (container !== document.body) { @@ -590,9 +589,9 @@ class Stage { * defaults to the viewer container * @return {undefined} */ - toggleFullscreen(element: HTMLElement) { + toggleFullscreen (element: HTMLElement) { if (!document.fullscreenEnabled && !document.mozFullScreenEnabled && - !document.webkitFullscreenEnabled && !document.msFullscreenEnabled + !document.webkitFullscreenEnabled && !document.msFullscreenEnabled ) { Log.log('fullscreen mode (currently) not possible') return @@ -604,12 +603,12 @@ class Stage { // - function getFullscreenElement() { + function getFullscreenElement () { return document.fullscreenElement || document.mozFullScreenElement || - document.webkitFullscreenElement || document.msFullscreenElement + document.webkitFullscreenElement || document.msFullscreenElement } - function resizeElement() { + function resizeElement () { if (!getFullscreenElement() && self.lastFullscreenElement) { const element = self.lastFullscreenElement element.style.width = element.dataset.normalWidth || '' @@ -671,7 +670,7 @@ class Stage { * @param {Boolean} flag - if true start rocking and stop spinning * @return {undefined} */ - setSpin(flag: boolean) { + setSpin (flag: boolean) { if (flag) { this.spinAnimation.resume(true) this.rockAnimation.pause(true) @@ -685,7 +684,7 @@ class Stage { * @param {Boolean} flag - if true start rocking and stop spinning * @return {undefined} */ - setRock(flag: boolean) { + setRock (flag: boolean) { if (flag) { this.rockAnimation.resume(true) this.spinAnimation.pause(true) @@ -698,7 +697,7 @@ class Stage { * Toggle spin * @return {undefined} */ - toggleSpin() { + toggleSpin () { this.setSpin(this.spinAnimation.paused) } @@ -706,11 +705,11 @@ class Stage { * Toggle rock * @return {undefined} */ - toggleRock() { + toggleRock () { this.setRock(this.rockAnimation.paused) } - setFocus(value: number) { + setFocus (value: number) { const clipNear = clamp(value / 2, 0, 49.9) const clipFar = 100 - clipNear const diffHalf = (clipFar - clipNear) / 2 @@ -723,7 +722,7 @@ class Stage { }) } - getZoomForBox(boundingBox: Box3) { + getZoomForBox (boundingBox: Box3) { const bbSize = boundingBox.getSize(tmpZoomVector) const maxSize = Math.max(bbSize.x, bbSize.y, bbSize.z) const minSize = Math.min(bbSize.x, bbSize.y, bbSize.z) @@ -742,15 +741,15 @@ class Stage { return -distance } - getBox() { + getBox () { return this.viewer.boundingBox } - getZoom() { + getZoom () { return this.getZoomForBox(this.getBox()) } - getCenter(optionalTarget?: Vector3) { + getCenter (optionalTarget?: Vector3) { return this.getBox().getCenter(optionalTarget || new Vector3()) } @@ -759,7 +758,7 @@ class Stage { * @param {Integer} duration - animation time in milliseconds * @return {undefined} */ - autoView(duration?: number) { + autoView (duration?: number) { this.animationControls.zoomMove( this.getCenter(), this.getZoom(), @@ -770,7 +769,7 @@ class Stage { /** * Make image from what is shown in a viewer canvas */ - makeImage(params: Partial = {}) { + makeImage (params: Partial = {}) { return new Promise((resolve, reject) => { this.tasks.onZeroOnce(() => { this.tasks.increment() @@ -785,7 +784,7 @@ class Stage { }) } - setImpostor(value: boolean) { + setImpostor (value: boolean) { this.parameters.impostor = value const types = [ @@ -803,7 +802,7 @@ class Stage { }) } - setQuality(value: RenderQualityType) { + setQuality (value: RenderQualityType) { this.parameters.quality = value const types = [ @@ -836,7 +835,7 @@ class Stage { /** * Iterator over each component and executing the callback */ - eachComponent(callback: (comp: Component) => void, type?: string) { + eachComponent (callback: (comp: Component) => void, type?: string) { this.compList.slice().forEach(comp => { if (type === undefined || type === comp.type) callback(comp) }) @@ -845,7 +844,7 @@ class Stage { /** * Iterator over each representation and executing the callback */ - eachRepresentation(callback: (reprElem: RepresentationElement, comp: Component) => void, type?: string) { + eachRepresentation (callback: (reprElem: RepresentationElement, comp: Component) => void, type?: string) { this.eachComponent(comp => { comp.reprList.slice().forEach(reprElem => { if (type === undefined || type === reprElem.getType()) callback(reprElem, comp) @@ -856,7 +855,7 @@ class Stage { /** * Get collection of components by name */ - getComponentsByName(name: string | RegExp) { + getComponentsByName (name: string|RegExp) { const compList: Component[] = [] this.eachComponent(comp => { @@ -869,7 +868,7 @@ class Stage { /** * Get collection of components by object */ - getComponentsByObject(object: Structure | Surface | Volume | Shape) { + getComponentsByObject (object: Structure|Surface|Volume|Shape) { const compList: Component[] = [] this.eachComponent(comp => { @@ -882,7 +881,7 @@ class Stage { /** * Get collection of representations by name */ - getRepresentationsByName(name: string | RegExp) { + getRepresentationsByName (name: string|RegExp) { const reprList: RepresentationElement[] = [] this.eachRepresentation((repr, comp) => { @@ -892,11 +891,11 @@ class Stage { return new RepresentationCollection(reprList) } - measureClear() { + measureClear () { this.eachComponent((sc: StructureComponent) => sc.measureClear(), 'structure') } - measureUpdate() { + measureUpdate () { this.eachComponent((sc: StructureComponent) => sc.measureUpdate(), 'structure') } @@ -923,11 +922,10 @@ class Stage { return comps } - /** * Cleanup when disposing of a stage object */ - dispose() { + dispose () { this.tasks.dispose() this.viewer.dispose() } diff --git a/src/structure/structure.ts b/src/structure/structure.ts index 42be53806..ebe1deb75 100644 --- a/src/structure/structure.ts +++ b/src/structure/structure.ts @@ -129,7 +129,7 @@ export type StructureSignals = { /** * Structure */ -class Structure implements Structure { +class Structure implements Structure{ signals: StructureSignals = { refreshed: new Signal() } @@ -138,11 +138,11 @@ class Structure implements Structure { * @param {String} name - structure name * @param {String} path - source path */ - constructor(name = '', path = '') { + constructor (name = '', path = '') { this.init(name, path) } - init(name: string, path: string) { + init (name: string, path: string) { this.name = name this.path = path this.title = '' @@ -191,9 +191,9 @@ class Structure implements Structure { this._cp = this.getChainProxy() } - get type() { return 'Structure' } + get type () { return 'Structure' } - finalizeAtoms() { + finalizeAtoms () { this.atomSet = this.getAtomSet() this.atomCount = this.atomStore.count this.boundingBox = this.getBoundingBox(undefined, this.boundingBox) @@ -201,7 +201,7 @@ class Structure implements Structure { this.spatialHash = new SpatialHash(this.atomStore, this.boundingBox) } - finalizeBonds() { + finalizeBonds () { this.bondSet = this.getBondSet() this.bondCount = this.bondStore.count this.bondHash = new BondHash(this.bondStore, this.atomStore.count) @@ -212,35 +212,35 @@ class Structure implements Structure { } for (let name in this.atomSetDict) { - this.atomSetCache['__' + name] = this.atomSetDict[name].clone() + this.atomSetCache[ '__' + name ] = this.atomSetDict[ name ].clone() } } // - getBondProxy(index?: number) { + getBondProxy (index?: number) { return new BondProxy(this, index) } - getAtomProxy(index?: number) { + getAtomProxy (index?: number) { return new AtomProxy(this, index) } - getResidueProxy(index?: number) { + getResidueProxy (index?: number) { return new ResidueProxy(this, index) } - getChainProxy(index?: number) { + getChainProxy (index?: number) { return new ChainProxy(this, index) } - getModelProxy(index?: number) { + getModelProxy (index?: number) { return new ModelProxy(this, index) } // - getBondSet(/* selection */) { + getBondSet (/* selection */) { // TODO implement selection parameter const n = this.bondStore.count @@ -269,7 +269,7 @@ class Structure implements Structure { return bondSet } - getBackboneBondSet(/* selection */) { + getBackboneBondSet (/* selection */) { // TODO implement selection parameter const n = this.backboneBondStore.count @@ -293,7 +293,7 @@ class Structure implements Structure { return backboneBondSet } - getRungBondSet(/* selection */) { + getRungBondSet (/* selection */) { // TODO implement selection parameter const n = this.rungBondStore.count @@ -326,7 +326,7 @@ class Structure implements Structure { * BitArray: return bit array * @return {BitArray} set of atoms */ - getAtomSet(selection?: boolean | Selection | BitArray) { + getAtomSet (selection?: boolean|Selection|BitArray) { const n = this.atomStore.count if (selection === undefined) { @@ -338,7 +338,7 @@ class Structure implements Structure { } else if (selection && selection.test) { const seleString = selection.string if (seleString in this.atomSetCache) { - return this.atomSetCache[seleString] + return this.atomSetCache[ seleString ] } else { if (seleString === '') { return new BitArray(n, true) @@ -347,7 +347,7 @@ class Structure implements Structure { this.eachAtom(function (ap: AtomProxy) { atomSet.set(ap.index) }, selection) - this.atomSetCache[seleString] = atomSet + this.atomSetCache[ seleString ] = atomSet return atomSet } } @@ -364,7 +364,7 @@ class Structure implements Structure { * @param {Number} radius - radius to select within * @return {BitArray} set of atoms */ - getAtomSetWithinSelection(selection: boolean | Selection | BitArray, radius: number) { + getAtomSetWithinSelection (selection: boolean|Selection|BitArray, radius: number) { const spatialHash = this.spatialHash const atomSet = this.getAtomSet(false) const ap = this.getAtomProxy() @@ -387,7 +387,7 @@ class Structure implements Structure { * @param {Number} radius - radius to select within * @return {BitArray} set of atoms */ - getAtomSetWithinPoint(point: Vector3 | AtomProxy, radius: number) { + getAtomSetWithinPoint (point: Vector3|AtomProxy, radius: number) { const p = point const atomSet = this.getAtomSet(false) @@ -409,7 +409,7 @@ class Structure implements Structure { * @param {[type]} outside - use only values falling outside of the min/max values * @return {BitArray} set of atoms */ - getAtomSetWithinVolume(volume: Volume, radius: number, minValue: number, maxValue: number, outside: boolean) { + getAtomSetWithinVolume (volume: Volume, radius: number, minValue: number, maxValue: number, outside: boolean) { const fv = new FilteredVolume(volume, minValue, maxValue, outside) as any // TODO const dp = fv.getDataPosition() @@ -420,7 +420,7 @@ class Structure implements Structure { if (!this.spatialHash) return atomSet for (let i = 0; i < n; i += 3) { - this.spatialHash.within(dp[i], dp[i + 1], dp[i + 2], r).forEach(function (idx) { + this.spatialHash.within(dp[ i ], dp[ i + 1 ], dp[ i + 2 ], r).forEach(function (idx) { atomSet.set(idx) }) } @@ -433,13 +433,13 @@ class Structure implements Structure { * @param {Selection} selection - the selection object * @return {BitArray} set of atoms */ - getAtomSetWithinGroup(selection: boolean | Selection) { + getAtomSetWithinGroup (selection: boolean|Selection) { const atomResidueIndex = this.atomStore.residueIndex const atomSet = this.getAtomSet(false) const rp = this.getResidueProxy() this.getAtomSet(selection).forEach(function (idx) { - rp.index = atomResidueIndex[idx] + rp.index = atomResidueIndex[ idx ] for (let idx2 = rp.atomOffset; idx2 <= rp.atomEnd; ++idx2) { atomSet.set(idx2) } @@ -450,11 +450,11 @@ class Structure implements Structure { // - getSelection(): false | Selection { + getSelection (): false|Selection { return false } - getStructure(): Structure | StructureView { + getStructure (): Structure|StructureView { return this } @@ -464,7 +464,7 @@ class Structure implements Structure { * @param {EntityType} type - entity type * @return {undefined} */ - eachEntity(callback: (entity: Entity) => void, type: number) { + eachEntity (callback: (entity: Entity) => void, type: number) { this.entityList.forEach(function (entity) { if (type === undefined || entity.getEntityType() === type) { callback(entity) @@ -478,7 +478,7 @@ class Structure implements Structure { * @param {Selection} [selection] - the selection * @return {undefined} */ - eachBond(callback: (entity: BondProxy) => void, selection?: Selection) { + eachBond (callback: (entity: BondProxy) => void, selection?: Selection) { const bp = this.getBondProxy() let bondSet @@ -509,7 +509,7 @@ class Structure implements Structure { * @param {Selection} [selection] - the selection * @return {undefined} */ - eachAtom(callback: (entity: AtomProxy) => void, selection?: Selection) { + eachAtom (callback: (entity: AtomProxy) => void, selection?: Selection) { if (selection && selection.test) { this.eachModel(function (mp) { mp.eachAtom(callback, selection) @@ -530,7 +530,7 @@ class Structure implements Structure { * @param {Selection} [selection] - the selection * @return {undefined} */ - eachResidue(callback: (entity: ResidueProxy) => void, selection?: Selection) { + eachResidue (callback: (entity: ResidueProxy) => void, selection?: Selection) { if (selection && selection.test) { const mn = this.modelStore.count const mp = this.getModelProxy() @@ -564,19 +564,19 @@ class Structure implements Structure { * @param {function(residueList: ResidueProxy[])} callback - the callback * @return {undefined} */ - eachResidueN(n: number, callback: (...entityArray: ResidueProxy[]) => void) { + eachResidueN (n: number, callback: (...entityArray: ResidueProxy[]) => void) { const rn = this.residueStore.count if (rn < n) return const array: ResidueProxy[] = new Array(n) for (let i = 0; i < n; ++i) { - array[i] = this.getResidueProxy(i) + array[ i ] = this.getResidueProxy(i) } callback.apply(this, array) for (let j = n; j < rn; ++j) { for (let i = 0; i < n; ++i) { - array[i].index += 1 + array[ i ].index += 1 } callback.apply(this, array) } @@ -588,7 +588,7 @@ class Structure implements Structure { * @param {Selection} [selection] - the selection * @return {undefined} */ - eachPolymer(callback: (entity: Polymer) => void, selection?: Selection) { + eachPolymer (callback: (entity: Polymer) => void, selection?: Selection) { if (selection && selection.modelOnlyTest) { const modelOnlyTest = selection.modelOnlyTest @@ -610,7 +610,7 @@ class Structure implements Structure { * @param {Selection} [selection] - the selection * @return {undefined} */ - eachChain(callback: (entity: ChainProxy) => void, selection?: Selection) { + eachChain (callback: (entity: ChainProxy) => void, selection?: Selection) { if (selection && selection.test) { this.eachModel(function (mp) { mp.eachChain(callback, selection) @@ -631,7 +631,7 @@ class Structure implements Structure { * @param {Selection} [selection] - the selection * @return {undefined} */ - eachModel(callback: (entity: ModelProxy) => void, selection?: Selection) { + eachModel (callback: (entity: ModelProxy) => void, selection?: Selection) { const n = this.modelStore.count const mp = this.getModelProxy() @@ -660,7 +660,7 @@ class Structure implements Structure { // - getAtomData(params: AtomDataParams) { + getAtomData (params: AtomDataParams) { const p = Object.assign({}, params) if (p.colorParams) p.colorParams.structure = this.getStructure() @@ -692,7 +692,7 @@ class Structure implements Structure { atomData.index = new Uint32Array(atomCount) } - const { position, color, picking, radius, index } = atomData + const {position, color, picking, radius, index} = atomData atomSet.forEach((idx: number, i: number) => { const i3 = i * 3 @@ -704,19 +704,19 @@ class Structure implements Structure { colormaker.atomColorToArray(ap, color, i3) } if (picking) { - picking.array![i] = idx + picking.array![ i ] = idx } if (radius) { - radius[i] = radiusFactory.atomRadius(ap) + radius[ i ] = radiusFactory.atomRadius(ap) } if (index) { - index[i] = idx + index[ i ] = idx } }) return atomData } - getBondData(params: BondDataParams) { + getBondData (params: BondDataParams) { const p = Object.assign({}, params) if (p.colorParams) p.colorParams.structure = this.getStructure() @@ -742,7 +742,7 @@ class Structure implements Structure { const storeBondOrder = bp.bondStore.bondOrder bondCount = 0 bondSet.forEach(function (index: number) { - bondCount += storeBondOrder[index] + bondCount += storeBondOrder[ index ] }) } else { bondCount = bondSet.getSize() @@ -770,7 +770,7 @@ class Structure implements Structure { } } - const { position1, position2, color, color2, picking, radius, radius2 } = bondData + const {position1, position2, color, color2, picking, radius, radius2} = bondData let i = 0 let j, i3, k, bondOrder, absOffset @@ -856,28 +856,28 @@ class Structure implements Structure { } } if (picking && picking.array) { - picking.array[i] = index + picking.array[ i ] = index if (isMulti && bondOrder > 1) { for (j = 1; j < bondOrder; ++j) { - picking.array[i + j] = index + picking.array[ i + j ] = index } } } if (radius) { - radius[i] = radiusFactory.atomRadius(ap1) + radius[ i ] = radiusFactory.atomRadius(ap1) if (isMulti && bondOrder > 1) { - multiRadius = radius[i] * bondScale / (isOffset ? 1 : (0.5 * bondOrder)) + multiRadius = radius[ i ] * bondScale / (isOffset ? 1 : (0.5 * bondOrder)) for (j = isOffset ? 1 : 0; j < bondOrder; ++j) { - radius[i + j] = multiRadius + radius[ i + j ] = multiRadius } } } if (radius2) { - radius2[i] = radiusFactory.atomRadius(ap2) + radius2[ i ] = radiusFactory.atomRadius(ap2) if (isMulti && bondOrder > 1) { - multiRadius = radius2[i] * bondScale / (isOffset ? 1 : (0.5 * bondOrder)) + multiRadius = radius2[ i ] * bondScale / (isOffset ? 1 : (0.5 * bondOrder)) for (j = isOffset ? 1 : 0; j < bondOrder; ++j) { - radius2[i + j] = multiRadius + radius2[ i + j ] = multiRadius } } } @@ -887,7 +887,7 @@ class Structure implements Structure { return bondData } - getBackboneAtomData(params: AtomDataParams) { + getBackboneAtomData (params: AtomDataParams) { params = Object.assign({ atomSet: this.atomSetCache.__backbone }, params) @@ -895,7 +895,7 @@ class Structure implements Structure { return this.getAtomData(params) } - getBackboneBondData(params: BondDataParams) { + getBackboneBondData (params: BondDataParams) { params = Object.assign({ bondSet: this.getBackboneBondSet(), bondStore: this.backboneBondStore @@ -904,7 +904,7 @@ class Structure implements Structure { return this.getBondData(params) } - getRungAtomData(params: AtomDataParams) { + getRungAtomData (params: AtomDataParams) { params = Object.assign({ atomSet: this.atomSetCache.__rung }, params) @@ -912,7 +912,7 @@ class Structure implements Structure { return this.getAtomData(params) } - getRungBondData(params: BondDataParams) { + getRungBondData (params: BondDataParams) { params = Object.assign({ bondSet: this.getRungBondSet(), bondStore: this.rungBondStore @@ -929,7 +929,7 @@ class Structure implements Structure { * @param {Box3} [box] - optional target * @return {Vector3} the box */ - getBoundingBox(selection?: Selection, box?: Box3) { + getBoundingBox (selection?: Selection, box?: Box3) { if (Debug) Log.time('getBoundingBox') box = box || new Box3() @@ -969,7 +969,7 @@ class Structure implements Structure { * @param {Selection} [selection] - the selection * @return {PrincipalAxes} the principal axes */ - getPrincipalAxes(selection?: Selection) { + getPrincipalAxes (selection?: Selection) { if (Debug) Log.time('getPrincipalAxes') let i = 0 @@ -977,9 +977,9 @@ class Structure implements Structure { const cd = coords.data this.eachAtom(a => { - cd[i + 0] = a.x - cd[i + 1] = a.y - cd[i + 2] = a.z + cd[ i + 0 ] = a.x + cd[ i + 1 ] = a.y + cd[ i + 2 ] = a.z i += 3 }, selection) @@ -993,7 +993,7 @@ class Structure implements Structure { * @param {Selection} [selection] - the selection * @return {Vector3} the center */ - atomCenter(selection?: Selection) { + atomCenter (selection?: Selection) { if (selection) { return this.getBoundingBox(selection).getCenter(new Vector3()) } else { @@ -1001,7 +1001,7 @@ class Structure implements Structure { } } - hasCoords() { + hasCoords () { if (this._hasCoords === undefined) { const atomStore = this.atomStore this._hasCoords = ( @@ -1009,14 +1009,14 @@ class Structure implements Structure { arrayMin(atomStore.y) !== 0 || arrayMax(atomStore.y) !== 0 || arrayMin(atomStore.z) !== 0 || arrayMax(atomStore.z) !== 0 ) || ( - // allow models with a single atom at the origin - atomStore.count / this.modelStore.count === 1 - ) + // allow models with a single atom at the origin + atomStore.count / this.modelStore.count === 1 + ) } return this._hasCoords; } - getSequence(selection?: Selection) { + getSequence (selection?: Selection) { const seq: string[] = [] const rp = this.getResidueProxy() @@ -1030,7 +1030,7 @@ class Structure implements Structure { return seq } - getAtomIndices(selection?: Selection) { + getAtomIndices (selection?: Selection) { if (selection && selection.string) { const indices: number[] = [] this.eachAtom(function (ap: AtomProxy) { @@ -1048,7 +1048,7 @@ class Structure implements Structure { * @param {Selection} selection - limit count to selection * @return {Integer} count */ - getChainnameCount(selection?: Selection) { + getChainnameCount (selection?: Selection) { const chainnames = new Set() this.eachChain(function (cp: ChainProxy) { if (cp.residueCount) { @@ -1061,7 +1061,7 @@ class Structure implements Structure { // - updatePosition(position: Float32Array | number[]) { + updatePosition (position: Float32Array|number[]) { let i = 0 this.eachAtom(function (ap: AtomProxy) { @@ -1072,7 +1072,7 @@ class Structure implements Structure { this._hasCoords = undefined // to trigger recalculation } - refreshPosition() { + refreshPosition () { this.getBoundingBox(undefined, this.boundingBox) this.boundingBox.getCenter(this.center) this.spatialHash = new SpatialHash(this.atomStore, this.boundingBox) @@ -1083,7 +1083,7 @@ class Structure implements Structure { * Unsets properties to help garbage collection. * @return {undefined} */ - dispose() { + dispose () { if (this.frames) this.frames.length = 0 if (this.boxes) this.boxes.length = 0 diff --git a/src/ui/parameters.ts b/src/ui/parameters.ts index fcdbfa927..c3b3ffe0b 100644 --- a/src/ui/parameters.ts +++ b/src/ui/parameters.ts @@ -7,32 +7,32 @@ import { StageParameters } from '../stage/stage' import { MouseActionPresets } from '../controls/mouse-actions' export type BooleanParam = { type: 'boolean' } -function BooleanParam() { return { type: 'boolean' } as BooleanParam } +function BooleanParam () { return { type: 'boolean' } as BooleanParam } export type ColorParam = { type: 'color' } -function ColorParam() { return { type: 'color' } as ColorParam } +function ColorParam () { return { type: 'color' } as ColorParam } export type IntegerParam = { type: 'integer', max: number, min: number } -function IntegerParam(max: number, min: number) { +function IntegerParam (max: number, min: number) { return { type: 'integer', max, min } as IntegerParam } export type NumberParam = { type: 'number', precision: number, max: number, min: number } -function NumberParam(precision: number, max: number, min: number) { +function NumberParam (precision: number, max: number, min: number) { return { type: 'number', precision, max, min } as NumberParam } export type RangeParam = { type: 'range', step: number, max: number, min: number } -function RangeParam(step: number, max: number, min: number) { +function RangeParam (step: number, max: number, min: number) { return { type: 'range', step, max, min } as RangeParam } export type SelectParam = { type: 'select', options: { [k: string]: string } } -function SelectParam(...options: string[]) { +function SelectParam (...options: string[]) { return { type: 'select', options: options.reduce((o, k) => ({ ...o, [k]: k }), {}) } as SelectParam } -export type ParamType = BooleanParam | ColorParam | IntegerParam | NumberParam | RangeParam | SelectParam +export type ParamType = BooleanParam|ColorParam|IntegerParam|NumberParam|RangeParam|SelectParam export const UIStageParameters: { [k in keyof StageParameters]: ParamType } = { backgroundColor: ColorParam(), diff --git a/src/viewer/viewer.ts b/src/viewer/viewer.ts index 2fe981cbe..368c571f4 100644 --- a/src/viewer/viewer.ts +++ b/src/viewer/viewer.ts @@ -48,12 +48,12 @@ const pixelBufferUint = new Uint8Array(4 * 25) // This starts at the center and tries successively further points. // (Many points will be at equal distance to the center, their order // is arbitrary). -const pixelOrder = [12, 7, 13, 17, 11, 6, 8, 18, 16, 2, 14, 22, 10, 1, 3, 9, 19, 23, 21, 15, 5, 0, 4, 24, 20] +const pixelOrder = [12,7,13,17,11,6,8,18,16,2,14,22,10,1,3,9,19,23,21,15,5,0,4,24,20] const tmpMatrix = new Matrix4() -function onBeforeRender(this: Object3D, renderer: WebGLRenderer, scene: Scene, camera: PerspectiveCamera | OrthographicCamera, geometry: Geometry, material: ShaderMaterial/*, group */) { +function onBeforeRender (this: Object3D, renderer: WebGLRenderer, scene: Scene, camera: PerspectiveCamera|OrthographicCamera, geometry: Geometry, material: ShaderMaterial/*, group */) { const u = material.uniforms const updateList = [] @@ -63,7 +63,7 @@ function onBeforeRender(this: Object3D, renderer: WebGLRenderer, scene: Scene, c } if (u.modelViewMatrixInverse || u.modelViewMatrixInverseTranspose || - u.modelViewProjectionMatrix || u.modelViewProjectionMatrixInverse + u.modelViewProjectionMatrix || u.modelViewProjectionMatrixInverse ) { this.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, this.matrixWorld) } @@ -122,13 +122,13 @@ function onBeforeRender(this: Object3D, renderer: WebGLRenderer, scene: Scene, c const pu = p.getUniforms() updateList.forEach(function (name) { - pu.setValue(gl, name, u[name].value) + pu.setValue(gl, name, u[ name ].value) }) } } } -export type CameraType = 'perspective' | 'orthographic' | 'stereo' +export type CameraType = 'perspective'|'orthographic'|'stereo' export interface ViewerSignals { ticked: Signal, @@ -189,7 +189,7 @@ export default class Viewer { perspectiveCamera: PerspectiveCamera private orthographicCamera: OrthographicCamera private stereoCamera: StereoCamera - camera: PerspectiveCamera | OrthographicCamera + camera: PerspectiveCamera|OrthographicCamera width: number height: number @@ -240,7 +240,7 @@ export default class Viewer { private distVector = new Vector3() - constructor(idOrElement: string | HTMLElement) { + constructor (idOrElement: string|HTMLElement) { this.signals = { ticked: new Signal(), rendered: new Signal() @@ -250,7 +250,7 @@ export default class Viewer { const elm = document.getElementById(idOrElement) if (elm === null) { this.container = document.createElement('div') - } else { + }else { this.container = elm } } else if (idOrElement instanceof HTMLElement) { @@ -292,7 +292,7 @@ export default class Viewer { this.animate = this.animate.bind(this) } - private _initParams() { + private _initParams () { this.parameters = { fogColor: new Color(0x000000), fogNear: 50, @@ -318,9 +318,9 @@ export default class Viewer { } } - private _initCamera() { + private _initCamera () { const lookAt = new Vector3(0, 0, 0) - const { width, height } = this + const {width, height} = this this.perspectiveCamera = new PerspectiveCamera( this.parameters.cameraFov, width / height @@ -341,7 +341,7 @@ export default class Viewer { const cameraType = this.parameters.cameraType if (cameraType === 'orthographic') { this.camera = this.orthographicCamera - } else if (cameraType === 'perspective' || cameraType === 'stereo') { + } else if(cameraType === 'perspective' || cameraType === 'stereo') { this.camera = this.perspectiveCamera } else { throw new Error(`Unknown cameraType '${cameraType}'`) @@ -349,11 +349,11 @@ export default class Viewer { this.camera.updateProjectionMatrix() } - private _initStats() { + private _initStats () { this.stats = new Stats() } - private _initScene() { + private _initScene () { if (!this.scene) { this.scene = new Scene() this.scene.name = 'scene' @@ -400,9 +400,9 @@ export default class Viewer { this.scene.add(this.ambientLight) } - private _initRenderer() { + private _initRenderer () { const dpr = window.devicePixelRatio - const { width, height } = this + const {width, height} = this try { this.renderer = new WebGLRenderer({ @@ -527,7 +527,7 @@ export default class Viewer { )) } - private _initHelper() { + private _initHelper () { const indices = new Uint16Array([ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 @@ -547,19 +547,19 @@ export default class Viewer { this.helperGroup.add(this.boundingBoxMesh) } - updateHelper() { + updateHelper () { const position = ((this.boundingBoxMesh.geometry as BufferGeometry).attributes as any).position // TODO const array = position.array - const { min, max } = this.boundingBox + const {min, max} = this.boundingBox - array[0] = max.x; array[1] = max.y; array[2] = max.z - array[3] = min.x; array[4] = max.y; array[5] = max.z - array[6] = min.x; array[7] = min.y; array[8] = max.z - array[9] = max.x; array[10] = min.y; array[11] = max.z - array[12] = max.x; array[13] = max.y; array[14] = min.z - array[15] = min.x; array[16] = max.y; array[17] = min.z - array[18] = min.x; array[19] = min.y; array[20] = min.z - array[21] = max.x; array[22] = min.y; array[23] = min.z + array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z + array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z + array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z + array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z + array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z + array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z + array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z + array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z position.needsUpdate = true @@ -568,7 +568,7 @@ export default class Viewer { } } - add(buffer: Buffer, instanceList?: BufferInstance[]) { + add (buffer: Buffer, instanceList?: BufferInstance[]) { // Log.time( "Viewer.add" ); if (instanceList) { @@ -594,10 +594,10 @@ export default class Viewer { // Log.timeEnd( "Viewer.add" ); } - addBuffer(buffer: Buffer, instance?: BufferInstance) { + addBuffer (buffer: Buffer, instance?: BufferInstance) { // Log.time( "Viewer.addBuffer" ); - function setUserData(object: Object3D) { + function setUserData (object: Object3D) { if (object instanceof Group) { object.children.forEach(setUserData) } else { @@ -647,7 +647,7 @@ export default class Viewer { // Log.timeEnd( "Viewer.addBuffer" ); } - remove(buffer: Buffer) { + remove (buffer: Buffer) { this.translationGroup.children.forEach(function (group) { group.remove(buffer.group) group.remove(buffer.wireframeGroup) @@ -663,10 +663,10 @@ export default class Viewer { // this.requestRender(); } - private _updateBoundingBox(geometry?: BufferGeometry, matrix?: Matrix4, instanceMatrix?: Matrix4) { + private _updateBoundingBox (geometry?: BufferGeometry, matrix?: Matrix4, instanceMatrix?: Matrix4) { const boundingBox = this.boundingBox - function updateGeometry(geometry: BufferGeometry, matrix?: Matrix4, instanceMatrix?: Matrix4) { + function updateGeometry (geometry: BufferGeometry, matrix?: Matrix4, instanceMatrix?: Matrix4) { if (!geometry.boundingBox) { geometry.computeBoundingBox() } @@ -689,7 +689,7 @@ export default class Viewer { boundingBox.union(geoBoundingBox) } - function updateNode(node: Mesh) { + function updateNode (node: Mesh) { if (node.geometry !== undefined) { let matrix, instanceMatrix if (node.userData.buffer) { @@ -714,13 +714,13 @@ export default class Viewer { this.boundingBoxLength = this.boundingBoxSize.length() } - updateBoundingBox() { + updateBoundingBox () { this._updateBoundingBox() if (Debug) this.updateHelper() } - getPickingPixels() { - const { width, height } = this + getPickingPixels () { + const {width, height} = this const n = width * height * 4 const imgBuffer = SupportsReadPixelsFloat ? new Float32Array(n) : new Uint8Array(n) @@ -733,17 +733,17 @@ export default class Viewer { return imgBuffer } - getImage(picking: boolean) { + getImage (picking: boolean) { return new Promise(resolve => { if (picking) { - const { width, height } = this + const {width, height} = this const n = width * height * 4 let imgBuffer = this.getPickingPixels() if (SupportsReadPixelsFloat) { const imgBuffer2 = new Uint8Array(n) for (let i = 0; i < n; ++i) { - imgBuffer2[i] = Math.round(imgBuffer[i] * 255) + imgBuffer2[ i ] = Math.round(imgBuffer[ i ] * 255) } imgBuffer = imgBuffer2 } @@ -762,11 +762,11 @@ export default class Viewer { }) } - makeImage(params: Partial = {}) { + makeImage (params: Partial = {}) { return makeImage(this, params) } - setLight(color: Color | number | string, intensity: number, ambientColor: Color | number | string, ambientIntensity: number) { + setLight (color: Color|number|string, intensity: number, ambientColor: Color|number|string, ambientIntensity: number) { const p = this.parameters if (color !== undefined) p.lightColor.set(color as string) // TODO @@ -777,7 +777,7 @@ export default class Viewer { this.requestRender() } - setFog(color?: Color | number | string, near?: number, far?: number) { + setFog (color?: Color|number|string, near?: number, far?: number) { const p = this.parameters if (color !== undefined) p.fogColor.set(color as string) // TODO @@ -787,7 +787,7 @@ export default class Viewer { this.requestRender() } - setBackground(color?: Color | number | string) { + setBackground (color?: Color|number|string) { const p = this.parameters if (color) p.backgroundColor.set(color as string) // TODO @@ -799,7 +799,7 @@ export default class Viewer { this.requestRender() } - setSampling(level: number) { + setSampling (level: number) { if (level !== undefined) { this.parameters.sampleLevel = level this.sampleLevel = level @@ -808,7 +808,7 @@ export default class Viewer { this.requestRender() } - setCamera(type: CameraType, fov?: number, eyeSep?: number) { + setCamera (type: CameraType, fov?: number, eyeSep?: number) { const p = this.parameters if (type) p.cameraType = type @@ -839,7 +839,7 @@ export default class Viewer { this.requestRender() } - setClip(near: number, far: number, dist: number) { + setClip (near: number, far: number, dist: number) { const p = this.parameters if (near !== undefined) p.clipNear = near @@ -849,7 +849,7 @@ export default class Viewer { this.requestRender() } - setSize(width: number, height: number) { + setSize (width: number, height: number) { this.width = width || 1 this.height = height || 1 @@ -875,7 +875,7 @@ export default class Viewer { this.requestRender() } - handleResize() { + handleResize () { if (this.container === document.body) { this.setSize(window.innerWidth, window.innerHeight) } else { @@ -884,7 +884,7 @@ export default class Viewer { } } - updateInfo(reset?: boolean) { + updateInfo (reset?: boolean) { const { memory, render } = this.info if (reset) { @@ -909,7 +909,7 @@ export default class Viewer { } } - animate() { + animate () { this.signals.ticked.dispatch(this.stats) const delta = window.performance.now() - this.stats.startTime @@ -926,7 +926,7 @@ export default class Viewer { window.requestAnimationFrame(this.animate) } - pick(x: number, y: number) { + pick (x: number, y: number) { if (this.parameters.cameraType === 'stereo') { // TODO picking broken for stereo camera return { @@ -954,7 +954,7 @@ export default class Viewer { const offset = pixelOrder[i] * 4 - const oid = Math.round(pixelBuffer[offset + 3]) + const oid = Math.round(pixelBuffer[ offset + 3 ]) const object = this.pickingGroup.getObjectById(oid) if (object) { instance = object.userData.instance @@ -993,7 +993,7 @@ export default class Viewer { return { pid, instance, picker } } - requestRender() { + requestRender () { if (this.renderPending) { // Log.info("there is still a 'render' call pending") return @@ -1013,13 +1013,13 @@ export default class Viewer { }) } - updateZoom() { + updateZoom () { const fov = degToRad(this.perspectiveCamera.fov) const height = 2 * Math.tan(fov / 2) * -this.camera.position.z this.orthographicCamera.zoom = this.height / height } - private __updateClipping() { + private __updateClipping () { const p = this.parameters // clipping @@ -1068,7 +1068,7 @@ export default class Viewer { } } - private __updateCamera() { + private __updateCamera () { const camera = this.camera camera.updateMatrix() camera.updateMatrixWorld(true) @@ -1078,14 +1078,14 @@ export default class Viewer { sortProjectedPosition(this.scene, camera) } - private __setVisibility(model: boolean, picking: boolean, background: boolean, helper: boolean) { + private __setVisibility (model: boolean, picking: boolean, background: boolean, helper: boolean) { this.modelGroup.visible = model this.pickingGroup.visible = picking this.backgroundGroup.visible = background this.helperGroup.visible = helper } - private __updateLights() { + private __updateLights () { this.spotLight.color.set(this.parameters.lightColor) this.spotLight.intensity = this.parameters.lightIntensity @@ -1096,7 +1096,7 @@ export default class Viewer { this.ambientLight.intensity = this.parameters.ambientIntensity } - private __renderPickingGroup(camera: PerspectiveCamera | OrthographicCamera) { + private __renderPickingGroup (camera: PerspectiveCamera|OrthographicCamera) { this.renderer.clearTarget(this.pickingTarget, true, true, true) this.__setVisibility(false, true, false, false) this.renderer.render(this.scene, camera, this.pickingTarget) @@ -1113,7 +1113,7 @@ export default class Viewer { // } } - private __renderModelGroup(camera: PerspectiveCamera | OrthographicCamera, renderTarget?: WebGLRenderTarget) { + private __renderModelGroup (camera: PerspectiveCamera|OrthographicCamera, renderTarget?: WebGLRenderTarget) { if (renderTarget) { this.renderer.clearTarget(renderTarget, true, true, true) } else { @@ -1134,14 +1134,14 @@ export default class Viewer { this.updateInfo() } - private __renderSuperSample(camera: PerspectiveCamera | OrthographicCamera) { + private __renderSuperSample (camera: PerspectiveCamera|OrthographicCamera) { // based on the Supersample Anti-Aliasing Render Pass // contributed to three.js by bhouston / http://clara.io/ // // This manual approach to SSAA re-renders the scene ones for // each sample with camera jitter and accumulates the results. // References: https://en.wikipedia.org/wiki/Supersampling - const offsetList = JitterVectors[Math.max(0, Math.min(this.sampleLevel, 5))] + const offsetList = JitterVectors[ Math.max(0, Math.min(this.sampleLevel, 5)) ] const baseSampleWeight = 1.0 / offsetList.length const roundingRange = 1 / 32 @@ -1157,9 +1157,9 @@ export default class Viewer { // render the scene multiple times, each slightly jitter offset // from the last and accumulate the results. for (let i = 0; i < offsetList.length; ++i) { - const offset = offsetList[i] + const offset = offsetList[ i ] camera.setViewOffset( - width, height, offset[0], offset[1], width, height + width, height, offset[ 0 ], offset[ 1 ], width, height ) camera.updateProjectionMatrix() updateCameraUniforms(this.scene, camera) @@ -1187,7 +1187,7 @@ export default class Viewer { this.renderer.render(this.compositeScene, this.compositeCamera, null!, true) } - private __renderStereo(picking = false) { + private __renderStereo (picking = false) { const stereoCamera = this.stereoCamera stereoCamera.update(this.perspectiveCamera); @@ -1210,7 +1210,7 @@ export default class Viewer { renderer.setViewport(0, 0, size.width, size.height) } - private __render(picking = false, camera: PerspectiveCamera | OrthographicCamera) { + private __render(picking = false, camera: PerspectiveCamera|OrthographicCamera) { if (picking) { if (!this.lastRenderedPicking) this.__renderPickingGroup(camera) } else if (this.sampleLevel > 0 && this.parameters.cameraType !== 'stereo') { @@ -1221,7 +1221,7 @@ export default class Viewer { } } - render(picking = false) { + render (picking = false) { if (this.rendering) { Log.warn("'tried to call 'render' from within 'render'") return @@ -1252,14 +1252,14 @@ export default class Viewer { // Log.log(this.info.memory, this.info.render) } - clear() { + clear () { Log.log('scene cleared') this.scene.remove(this.rotationGroup) this._initScene() this.renderer.clear() } - dispose() { + dispose () { this.renderer.dispose() } } \ No newline at end of file From 52750f0802b42acfed3f6d5333c4035538302fb5 Mon Sep 17 00:00:00 2001 From: Lily Wang Date: Tue, 18 Jun 2019 15:28:34 +1000 Subject: [PATCH 15/16] removed more autoformatting --- src/component/structure-component.ts | 16 ++++++++-------- src/controls/mouse-actions.ts | 13 +++++++------ src/stage/mouse-observer.ts | 2 -- src/ui/parameters.ts | 2 +- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/component/structure-component.ts b/src/component/structure-component.ts index a4da13abf..19eac06d3 100644 --- a/src/component/structure-component.ts +++ b/src/component/structure-component.ts @@ -30,7 +30,7 @@ import { createToggleSet, ToggleSet } from '../utils/toggle-set'; export type StructureRepresentationType = ( 'angle'|'axes'|'backbone'|'ball+stick'|'base'|'cartoon'|'contact'|'dihedral' | 'distance'|'helixorient'|'hyperball'|'label'|'licorice'|'line'|'surface' | - 'ribbon'|'rocket'|'rope'|'selected'|'spacefill'|'trace'|'tube'|'unitcell'|'selected' + 'ribbon'|'rocket'|'rope'|'selected'|'spacefill'|'trace'|'tube'|'unitcell' ) export const StructureComponentDefaultParameters = Object.assign({ @@ -397,10 +397,10 @@ class StructureComponent extends Component { const radiusData: { [k: number]: number } = {} pickData.forEach(ai => { const r = Math.max(0.1, this.getMaxRepresentationRadius(ai)) - radiusData[ai] = r * (2.3 - smoothstep(0.1, 2, r)) + radiusData[ ai ] = r * (2.3 - smoothstep(0.1, 2, r)) }) this.spacefillRepresentation.setSelection( - pickData.length ? ('@' + pickData.join(',')) : 'none' + pickData.length ? ( '@' + pickData.join(',') ) : 'none' ) this.spacefillRepresentation.setParameters({ radiusData }) } @@ -440,7 +440,7 @@ class StructureComponent extends Component { /** * Add a measurement given as a pair, triple, quad of atom indices */ - addMeasurement(atomList: number[]) { + addMeasurement (atomList: number[]) { if (atomList.length < 2 || atomList.length > 4) return const atomListSorted = atomList.slice().sort() if (!this.pickDict.has(atomListSorted)) { @@ -449,7 +449,7 @@ class StructureComponent extends Component { this.measureBuild() } - selectedPick(atoms: AtomProxy[]) { + selectedPick (atoms: AtomProxy[]) { let atomIndices: number[] = [] atoms.forEach(function (x) { atomIndices.push(x.index) @@ -457,12 +457,12 @@ class StructureComponent extends Component { this.selectedPickIndices(atomIndices) } - selectedPickIndices(atomIndices: number[]) { + selectedPickIndices (atomIndices: number[]) { this.selectedAtomIndices.toggleAny(atomIndices) this.selectedUpdate() } - setSelectedIndices(atomIndices: number[]) { + setSelectedIndices (atomIndices: number[]) { this.selectedAtomIndices.clear() for (var i = 0; i < atomIndices.length; i++) { this.selectedAtomIndices.add(atomIndices[i]) @@ -471,7 +471,7 @@ class StructureComponent extends Component { } - selectedUpdate() { + selectedUpdate () { const pickData = this.selectedAtomIndices.list const radiusData: { [k: number]: number } = {} pickData.forEach(ai => { diff --git a/src/controls/mouse-actions.ts b/src/controls/mouse-actions.ts index a085e83e4..c0365010d 100644 --- a/src/controls/mouse-actions.ts +++ b/src/controls/mouse-actions.ts @@ -231,7 +231,6 @@ class MouseActions { } } - static measurePick (stage: Stage, pickingProxy: PickingProxy) { if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) { const atom = pickingProxy.atom || pickingProxy.closestBondAtom @@ -264,7 +263,7 @@ class MouseActions { } } -type MouseActionPreset = [string, MouseActionCallback][] +type MouseActionPreset = [ string, MouseActionCallback ][] export const MouseActionPresets = { default: [ [ 'scroll', MouseActions.zoomScroll ], @@ -280,6 +279,8 @@ export const MouseActionPresets = { [ 'drag-shift-left', MouseActions.zoomDrag ], [ 'drag-middle', MouseActions.zoomFocusDrag ], + [ 'drag-ctrl-shift-right', MouseActions.panComponentDrag ], + [ 'drag-ctrl-shift-left', MouseActions.rotateComponentDrag ], [ 'clickPick-shift-left', MouseActions.selectPick ], [ 'doubleClick-shift-left', MouseActions.clearSelect ], @@ -287,7 +288,7 @@ export const MouseActionPresets = { [ 'clickPick-ctrl-left', MouseActions.measurePick ], [ 'clickPick-middle', MouseActions.movePick ], [ 'clickPick-left', MouseActions.movePick ], - [ 'hoverPick', MouseActions.tooltipPick] + [ 'hoverPick', MouseActions.tooltipPick ] ] as MouseActionPreset, pymol: [ [ 'drag-left', MouseActions.rotateDrag ], @@ -296,7 +297,7 @@ export const MouseActionPresets = { [ 'drag-shift-right', MouseActions.focusScroll ], [ 'clickPick-ctrl+shift-middle', MouseActions.movePick ], - [ 'hoverPick', MouseActions.tooltipPick] + [ 'hoverPick', MouseActions.tooltipPick ] ] as MouseActionPreset, coot: [ [ 'scroll', MouseActions.isolevelScroll ], @@ -308,7 +309,7 @@ export const MouseActionPresets = { [ 'drag-ctrl-right', MouseActions.focusScroll ], [ 'clickPick-middle', MouseActions.movePick ], - [ 'hoverPick', MouseActions.tooltipPick] + [ 'hoverPick', MouseActions.tooltipPick ] ] as MouseActionPreset, astexviewer: [ [ 'drag-left', MouseActions.rotateDrag ], @@ -316,7 +317,7 @@ export const MouseActionPresets = { [ 'drag-shift-left', MouseActions.zoomDrag ], [ 'scroll', MouseActions.focusScroll ], [ 'clickPick-middle', MouseActions.movePick ], - [ 'hoverPick', MouseActions.tooltipPick] + [ 'hoverPick', MouseActions.tooltipPick ] ] as MouseActionPreset } diff --git a/src/stage/mouse-observer.ts b/src/stage/mouse-observer.ts index 6891830a4..63fb1724b 100644 --- a/src/stage/mouse-observer.ts +++ b/src/stage/mouse-observer.ts @@ -256,7 +256,6 @@ class MouseObserver { * handle mouse move * @emits {MouseSignals.moved} when moved * @emits {MouseSignals.dragged} when dragged - * @emits {MouseSignals.draggedXY} when dragged * @param {Event} event - mouse event * @return {undefined} */ @@ -311,7 +310,6 @@ class MouseObserver { } this._setKeys(event) const cp = this.canvasPosition - this.signals.dropped.dispatch(); if (this._distance() < 4) { this.lastClicked = window.performance.now() if (this.doubleClickPending && this.prevClickCP.distanceTo(cp) < 4) { diff --git a/src/ui/parameters.ts b/src/ui/parameters.ts index c3b3ffe0b..813539978 100644 --- a/src/ui/parameters.ts +++ b/src/ui/parameters.ts @@ -29,7 +29,7 @@ function RangeParam (step: number, max: number, min: number) { export type SelectParam = { type: 'select', options: { [k: string]: string } } function SelectParam (...options: string[]) { - return { type: 'select', options: options.reduce((o, k) => ({ ...o, [k]: k }), {}) } as SelectParam + return { type: 'select', options: options.reduce((o, k) => ({ ...o, [k]: k}), {}) } as SelectParam } export type ParamType = BooleanParam|ColorParam|IntegerParam|NumberParam|RangeParam|SelectParam From 3a1115374c3b4aaa393780b2bb0509f5206dfd90 Mon Sep 17 00:00:00 2001 From: Lily Wang Date: Tue, 18 Jun 2019 16:25:58 +1000 Subject: [PATCH 16/16] unformatted mouse-observer --- src/component/structure-component.ts | 4 ++-- src/stage/mouse-observer.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/component/structure-component.ts b/src/component/structure-component.ts index 19eac06d3..d6a374afe 100644 --- a/src/component/structure-component.ts +++ b/src/component/structure-component.ts @@ -28,8 +28,8 @@ import { Vector3, Box3 } from 'three'; import { createToggleSet, ToggleSet } from '../utils/toggle-set'; export type StructureRepresentationType = ( - 'angle'|'axes'|'backbone'|'ball+stick'|'base'|'cartoon'|'contact'|'dihedral' | - 'distance'|'helixorient'|'hyperball'|'label'|'licorice'|'line'|'surface' | + 'angle'|'axes'|'backbone'|'ball+stick'|'base'|'cartoon'|'contact'|'dihedral'| + 'distance'|'helixorient'|'hyperball'|'label'|'licorice'|'line'|'surface'| 'ribbon'|'rocket'|'rope'|'selected'|'spacefill'|'trace'|'tube'|'unitcell' ) diff --git a/src/stage/mouse-observer.ts b/src/stage/mouse-observer.ts index 63fb1724b..5b2ab4894 100644 --- a/src/stage/mouse-observer.ts +++ b/src/stage/mouse-observer.ts @@ -32,7 +32,7 @@ function getTouchDistance (event: TouchEvent) { } function getMouseButtons (event: MouseEvent) { - if (typeof event === 'object') { + if (typeof event === 'object') { if ('buttons' in event) { return event.buttons } else if ('which' in event as any) { @@ -70,7 +70,7 @@ export interface MouseSignals { export interface MouseParams { hoverTimeout?: number - handleScroll?: boolean + handleScroll?:boolean doubleClickSpeed?: number } @@ -113,7 +113,7 @@ class MouseObserver { } hoverTimeout: number - handleScroll: boolean + handleScroll:boolean doubleClickSpeed: number viewer: Viewer