import { Component } from /**/"./Component.js"; let Toolkit; /////////////////////////////////////////////////////////////////////////////// // ScrollBar // /////////////////////////////////////////////////////////////////////////////// // Range picker with track, scroll box and scroll buttons class ScrollBar extends Component { static Component = Component; ///////////////////////// Initialization Methods ////////////////////////// constructor(gui, options) { super(gui, options, { className: "tk tk-scrollbar", focusable: true, role : "scrollbar", tabStop : true, tagName : "div", style : { alignItems : "stretch", display : "flex", flexDirection: "column" } }); // Configure instance fields this.extent = 50; this.increment = 1; this.isEnabled = true; this.maximum = 100; this.minimum = 0; this.orientation = "vertical"; this.value = 25; // Unit decrement button this.unitDown = document.createElement("div"); this.unitDown.className = "tk tk-unit-down"; this.append(this.unitDown); this.unitDown.addEventListener("pointerdown", e=>this.onIncrementPointerDown(e)); this.unitDown.addEventListener("pointermove", e=>this.onIncrementPointerMove(e)); this.unitDown.addEventListener("pointerup" , e=>this.onIncrementPointerUp (e)); // Block decrement track this.blockDown = document.createElement("div"); this.blockDown.className = "tk tk-block-down"; this.append(this.blockDown); this.blockDown.addEventListener("pointerdown", e=>this.onIncrementPointerDown(e)); this.blockDown.addEventListener("pointermove", e=>this.onIncrementPointerMove(e)); this.blockDown.addEventListener("pointerup" , e=>this.onIncrementPointerUp (e)); // Scroll box this.thumb = document.createElement("div"); this.thumb.className = "tk tk-thumb"; this.append(this.thumb); this.thumb.addEventListener("pointerdown", e=>this.onThumbPointerDown(e)); this.thumb.addEventListener("pointermove", e=>this.onThumbPointerMove(e)); this.thumb.addEventListener("pointerup" , e=>this.onThumbPointerUp (e)); // Block increment track this.blockUp = document.createElement("div"); this.blockUp.className = "tk tk-block-up"; this.append(this.blockUp); this.blockUp.addEventListener("pointerdown", e=>this.onIncrementPointerDown(e)); this.blockUp.addEventListener("pointermove", e=>this.onIncrementPointerMove(e)); this.blockUp.addEventListener("pointerup" , e=>this.onIncrementPointerUp (e)); // Unit increment track this.unitUp = document.createElement("div"); this.unitUp.className = "tk tk-unit-up"; this.append(this.unitUp); this.unitUp.addEventListener("pointerdown", e=>this.onIncrementPointerDown(e)); this.unitUp.addEventListener("pointermove", e=>this.onIncrementPointerMove(e)); this.unitUp.addEventListener("pointerup" , e=>this.onIncrementPointerUp (e)); // Configure component options = options || {}; this.setOrientation("vertical", true); this.addEventListener("resize", ()=>this.update()); this.addEventListener("keydown", e=>this.onKeyDown(e)); if ("enabled" in options) this.setEnabled (options.enabled ); if ("extent" in options) this.setExtent (options.extent , true); if ("increment" in options) this.setIncrement (options.increment , true); if ("minimum" in options) this.setMinimum (options.minimum , true); if ("maximum" in options) this.setMaximum (options.maximum , true); if ("orientation" in options) this.setOrientation(options.orientation, true); this.setValue("value" in options ? options.value : Math.round((this.minimum + this.maximum - this.extent) / 2)); } ///////////////////////////// Event Listeners ///////////////////////////// // Increment pointer down onIncrementPointerDown(e) { this.focus(); // Error checking if ( !this.isEnabled || e.button != 0 || this.extent >= this.maximum - this.minimum || e.target.hasPointerCapture(e.pointerCapture) ) return; // Configure event e.target.setPointerCapture(e.pointerId); e.stopPropagation(); e.preventDefault(); // Configure element e.target.classList.add("tk-active"); } // Increment pointer move onIncrementPointerMove(e) { // Error checking if (!e.target.hasPointerCapture(e.pointerId)) return; // Configure event e.stopPropagation(); e.preventDefault(); // Determine whether the event is within the element's bounds let bounds = e.target.getBoundingClientRect(); e.target.classList[ e.offsetX >= 0 && e.offsetX < bounds.width && e.offsetY >= 0 && e.offsetY < bounds.height ? "add" : "remove" ]("tk-active"); } // Increment pointer up onIncrementPointerUp(e) { // Error checking if (!e.target.hasPointerCapture(e.pointerId) || e.button != 0) return; // Configure event e.target.releasePointerCapture(e.pointerId); e.stopPropagation(); e.preventDefault(); // Configure component e.target.classList.remove("tk-active"); // Take the appropriate action let bounds = e.target.getBoundingClientRect(); if ( e.offsetX >= 0 && e.offsetX < bounds.width && e.offsetY >= 0 && e.offsetY < bounds.height ) switch (e.target) { case this.blockDown: this.setValue(this.value - this.extent ); break; case this.blockUp: this.setValue(this.value + this.extent ); break; case this.unitDown: this.setValue(this.value - this.increment); break; case this.unitUp: this.setValue(this.value + this.increment); break; } } // Scroll bar key press onKeyDown(e) { // Error checking if (!this.isEnabled) return; // Processing by key switch (e.key) { // Arrow key navigation case "ArrowDown": if (this.orientation == "horizontal") return; this.setValue(this.value + this.increment); break; case "ArrowLeft": if (this.orientation == "vertical") return; this.setValue(this.value - this.increment); break; case "ArrowRight": if (this.orientation == "vertical") return; this.setValue(this.value + this.increment); break; case "ArrowUp": if (this.orientation == "horizontal") return; this.setValue(this.value - this.increment); break; // Page key navigation case "PageDown": this.setValue(this.value + this.extent); break; case "PageUp": this.setValue(this.value - this.extent); break; // Cancel a thumb drag case "Escape": // No thumb drag is in progress if ( this.drag == null || !this.thumb.hasPointerCapture(this.drag.pointerId) ) return; // Cancel the thumb drag this.thumb.releasePointerCapture(this.drag.pointerId); this.setValue(this.drag.value); this.drag = null; break; default: return; } // Configure element e.stopPropagation(); e.preventDefault(); } // Thumb pointer down onThumbPointerDown(e) { this.focus(); // Error checking if ( !this.isEnabled || e.button != 0 || this.extent >= this.maximum - this.minimum || this.thumb.hasPointerCapture(e.pointerId) ) return; // Configure event this.thumb.setPointerCapture(e.pointerId); e.stopPropagation(); e.preventDefault(); // Begin dragging this.measure(); this.drag = { pointerId: e.pointerId, thumbPos : this.thumbPos, value : this.value, x : e.screenX / devicePixelRatio, y : e.screenY / devicePixelRatio }; } // Thumb pointer move onThumbPointerMove(e) { // Error checking if (!this.thumb.hasPointerCapture(e.pointerId)) return; // Configure event e.stopPropagation(); e.preventDefault(); // Update the thumb's position and potentially the value let delta = this.orientation == "horizontal" ? e.screenX / devicePixelRatio - this.drag.x : e.screenY / devicePixelRatio - this.drag.y ; this.update(this.drag.thumbPos + delta); } // Thumb pointer up onThumbPointerUp(e) { // Error checking if (!this.thumb.hasPointerCapture(e.pointerId) || e.button != 0) return; // Configure event this.thumb.releasePointerCapture(e.pointerId); e.stopPropagation(); e.preventDefault(); // Configure instance fields this.drag = null; } ///////////////////////////// Public Methods ////////////////////////////// // Specify whether or not the scroll bar is enabled setEnabled(enabled) { enabled = !!enabled; if (enabled == this.isEnabled) return; this.isEnabled = enabled; this.setAttribute("aria-disabled", !enabled); this.update(); } // Specify how many scroll units are currently visible setExtent(extent, noUpdate) { // Error checking extent = parseInt(extent); if (isNaN(extent)) return; // Configure instance fields this.extent = Math.max(0, extent); // Update elements this.setAttribute("aria-valuemax", Math.max(this.minimum, this.maximum - this.extent)); if (!noUpdate) this.update(); } // Specify the value change when clicking a unit scroll button setIncrement(increment) { // Error checking increment = parseInt(increment); if (isNaN(increment) || increment < 1) return; // Configure instance fields this.increment = increment; } // Specify the maximum scroll value setMaximum(maximum, noUpdate) { // Error checking maximum = parseInt(maximum); if (isNaN(maximum)) return; // Update maximum this.maximum = maximum; this.setAttribute("aria-valuemax", maximum); // Update other properties as needed if (maximum < this.minimum) this.setMinimum(maximum , true); if (maximum - this.extent < this.value) this.setValue (maximum - this.extent , true); // Update elements this.setAttribute("aria-valuemax", Math.max(this.minimum, this.maximum - this.extent)); if (!noUpdate) this.update(); } // Specify the minimum scroll value setMinimum(minimum, noUpdate) { // Error checking minimum = parseInt(minimum); if (isNaN(minimum)) return; // Update minimum this.minimum = minimum; this.setAttribute("aria-valuemin", minimum); // Update other properties as needed if (minimum > this.maximum) this.setMaximum(minimum, true); if (minimum > this.value) this.setValue (minimum, true); // Update elements if (!noUpdate) this.update(); } // Specify the widget's orientation setOrientation(orientation, noUpdate) { // Configure element switch (orientation) { case "horizontal": this.element.style.flexDirection = "row"; this.element.setAttribute("aria-orientation", "horizontal"); break; case "vertical": this.element.style.flexDirection = "column"; this.element.setAttribute("aria-orientation", "vertical"); break; default: return; } // Configure instance fields this.orientation = orientation; // Update elements if (!noUpdate) this.update(); } // Specify the current scroll value setValue(value, noUpdate) { // Error checking value = parseInt(value); if (isNaN(value) || value == this.value) return; // Update value value = Math.max(this.minimum, Math.min(value, this.maximum - this.extent)); if (value == this.value) return; this.value = value; this.setAttribute("aria-valuenow", value); // Update elements if (!noUpdate) this.update(); // Notify event listeners this.event("input", { value: value }); } ///////////////////////////// Package Methods ///////////////////////////// // Update the global Toolkit object static setToolkit(toolkit) { Toolkit = toolkit; } // Configure elements given the current widget state update(thumbPos) { this.measure(); // Update the value according to the given thumb position if (thumbPos !== undefined) { let maxPos = this.trackSize - this.thumbSize; thumbPos = Math.max(0, Math.min(maxPos, thumbPos)); this.setValue(Math.round( this.minimum + thumbPos / maxPos * (this.maximum - this.extent - this.minimum) ), true); } // Reposition the thumb according to current value else { thumbPos = Math.round( (this.trackSize - this.thumbSize ) * (this.value - this.minimum) / (this.maximum - this.extent - this.minimum) ); } // Configure elements this.thumb .style.flexBasis = this.thumbSize + "px"; this.blockDown.style.flexBasis = thumbPos + "px"; this.blockUp .style.flexBasis = (this.trackSize - this.thumbSize - thumbPos) + "px"; this.element.classList[ this.isEnabled && this.extent >= this.maximum - this.minimum ? "add" : "remove" ]("tk-full"); } ///////////////////////////// Private Methods ///////////////////////////// // Measure the current dimensions of widget components measure() { let bndBlockDown = this.blockDown.getBoundingClientRect(); let bndThis = this.getBounds(); let bndUnitDown = this.unitDown.getBoundingClientRect(); let bndUnitUp = this.unitUp .getBoundingClientRect(); let dim = this.orientation=="horizontal" ? "width" : "height"; // Track size is total size less the unit buttons this.trackSize = bndThis[dim] - bndUnitDown[dim] - bndUnitUp[dim]; // Thumb size is proportional to extent this.thumbSize = Math.max(0, Math.min(this.trackSize, Math.max(4, this.minimum == this.maximum ? this.trackSize : Math.round( this.trackSize * this.extent / (this.maximum - this.minimum) ) ))); // Thumb position is the size of the block down track this.thumbPos = bndBlockDown[dim]; } }; /////////////////////////////////////////////////////////////////////////////// // ScrollPane // /////////////////////////////////////////////////////////////////////////////// // Scrolling viewport for an external view class ScrollPane extends Component { //////////////////////////////// Constants //////////////////////////////// // Scroll bar policies static ALWAYS = 0; static AS_NEEDED = 1; static NEVER = 2; ///////////////////////// Initialization Methods ////////////////////////// constructor(gui, options) { super(gui, options, { className: "tk tk-scrollpane", tagName : "div", style : { overflow: "hidden", position: "relative" } }); // Configure instance fields this.view = null; this.viewResize = null; // Viewport this.viewport = document.createElement("div"); this.viewport.className = "tk tk-viewport"; Object.assign(this.viewport.style, { position: "absolute", bottom : "0", left : "0", overflow: "hidden", right : "0", top : "0" }); this.append(this.viewport); // Vertical scroll bar this.vertical = new ScrollBar(gui, { orientation: "vertical", visibility : true, style : { bottom : "0", position: "absolute", right : "0", top : "0" } }); this.append(this.vertical); this.vertical.addEventListener("input", e=>this.onVerticalScroll(e)); // Horizontal scroll bar this.horizontal = new ScrollBar(gui, { orientation: "horizontal", visibility : true, style : { bottom : "0", left : "0", position: "absolute", right : "0" } }); this.append(this.horizontal); this.horizontal.addEventListener("input", e=>this.onHorizontalScroll(e)); // Configure component options = options || {}; this.viewport.addEventListener("scroll", e=>this.onScroll(e)); this.addEventListener("resize" , ()=>this.update()); this.addEventListener("pointerdown", ()=>this.focus (), true); if ("horizontal" in options) this.setPolicy("horizontal", options.horizontal, true); if ("vertical" in options) this.setPolicy("vertical" , options.vertical , true); if ("view" in options) this.setView (options.view , true); this.update(); } ///////////////////////////// Event Handlers ////////////////////////////// // Horizontal scroll bar scroll onHorizontalScroll(e) { if (this.view != null) this.viewport.scrollLeft = e.value; } // Placeholder for element resize onResize(e) { } // Viewport scrolled onScroll(e) { this.horizontal.setValue(this.viewport.scrollLeft); this.vertical .setValue(this.viewport.scrollTop ); } // Vertical scroll bar scroll onVerticalScroll(e) { if (this.view != null) this.viewport.scrollTop = e.value; } ///////////////////////////// Public Methods ////////////////////////////// // Specify a scroll bar visibility policy setPolicy(orientation, value, noUpdate) { // Error checking switch (orientation) { case "horizontal": break; case "vertical" : break; default : return; } switch (value) { case ScrollPane.ALWAYS : break; case ScrollPane.AS_NEEDED: break; case ScrollPane.NEVER : break; default : return; } // Configure instance fields this[orientation].policy = value; // Update elements if (!noUpdate) this.update(); } // Specify the internal view setView(view, noUpdate) { // Error checking if (view == this.view) return; // Remove the previous view if (this.view != null) { if (Toolkit.isComponent(this.view)) { this.view.parent = null; this.view.element.remove; this.view.removeEventListener("scroll", this.viewScroll); } else this.view.remove(); Toolkit.removeResizeListener(this.viewResize); } // Error checking if (!(view instanceof Element || Toolkit.isComponent(view))) view = null; // Associate the new view if (view != null) { this.viewport.append(view instanceof Element?view:view.element); if (Toolkit.isComponent(view)) view.parent = this; } // Configure instance fields this.view = view; // Monitor events if (view) { if (Toolkit.isComponent(view)) view = view.element; this.viewResize = e=>this.onResize(e); Toolkit.addResizeListener(view, this.viewResize); } // Update elements if (!noUpdate) this.update(); } ///////////////////////////// Private Methods ///////////////////////////// // Configure elements given the current widget state update(noUpdate) { let bndHorz = this.horizontal.getBounds(); let bndThis = this .getBounds(); let bndVert = this.vertical .getBounds(); // Configure the initial dimensions of the viewport let height = bndThis.height; let width = bndThis.width; // Determine the view element let view = Toolkit.isComponent(this.view)?this.view.element:this.view; // Check whether the horizontal scroll bar is visible let horz = this.horizontal.policy == ScrollPane.ALWAYS || this.horizontal.policy != ScrollPane.NEVER && view != null && width < view.scrollWidth ; if (horz) height = Math.max(0, bndThis.height - bndHorz.height); // Check whether the vertical scroll bar is visible let vert = this.vertical.policy == ScrollPane.ALWAYS || this.vertical.policy != ScrollPane.NEVER && view != null && height < view.scrollHeight ; if (vert) width = Math.max(0, bndThis.width - bndVert.width); // Check the horizontal scroll bar again if (!horz) { horz = this.horizontal.policy != ScrollPane.NEVER && view != null && width < view.scrollWidth ; // The vertical scroll bar necessitated the horizontal scroll bar if (horz) height = Math.max(0, bndThis.height - bndHorz.height); } // Resize the viewport Object.assign(this.viewport.style, { height: height + "px", width : width + "px" }); // Configure horizontal scroll bar this.horizontal.setMaximum( view == null ? 0 : view.scrollWidth, true); this.horizontal.setExtent(this.view == null ? 0 : width); this.horizontal.setVisible(horz); this.horizontal.element.style.right = vert ? bndVert.width + "px" : 0; // Configure vertical scroll bar this.vertical.setMaximum( view == null ? 0 : view.scrollHeight, true); this.vertical.setExtent(view == null ? 0 : height); this.vertical.setVisible(vert); this.vertical.element.style.bottom = horz ? bndHorz.height + "px" : 0; } } /////////////////////////////////////////////////////////////////////////////// // SplitPane // /////////////////////////////////////////////////////////////////////////////// // Window splitter with resizable regions class SplitPane extends Component { //////////////////////////////// Constants //////////////////////////////// // Edges static BOTTOM = 0; static LEFT = 1; static RIGHT = 2; static TOP = 3; ///////////////////////// Initialization Methods ////////////////////////// constructor(gui, options) { super(gui, options, { className: "tk tk-splitpane", tagName : "div", style : { alignItems : "stretch", display : "flex", flexDirection: "row" } }); // Configure instance fields this.collapsed = null; this.increment = 10; // Configure top/left region this[0] = document.createElement("div"); this[0].className = "tk tk-a"; this[0].id = Toolkit.id(); Object.assign(this[0].style, { alignItems : "stretch", display : "grid", gridTemplateRows: "auto", justifyContent : "stretch" }); // Configure the bottom/right region this[1] = document.createElement("div"); this[1].className = "tk tk-b"; Object.assign(this[1].style, { alignItems : "stretch", display : "grid", gridTemplateRows: "auto", justifyContent : "stretch" }); // Configure the splitter this.splitter = new Toolkit.Component(gui, { className: "tk tk-splitter", focusable: true, role : "separator", tagName : "div", }); this.splitter.setAttribute("aria-controls", this[0].id); this.splitter.addEventListener("keydown" ,e=>this.onKeyDown (e)); this.splitter.addEventListener("pointerdown",e=>this.onPointerDown(e)); this.splitter.addEventListener("pointermove",e=>this.onPointerMove(e)); this.splitter.addEventListener("pointerup" ,e=>this.onPointerUp (e)); // Configure layout this.append(this[0]); this.append(this.splitter); this.append(this[1]); // Configure component options = options || {}; this.setEdge(("edge" in options) ? options.edge : SplitPane.LEFT); this.addEventListener("resize", e=>this.measure()); } ///////////////////////////// Event Handlers ////////////////////////////// // Key press onKeyDown(e) { let args = this.getArgs(); // Dragging is in progress if (this.drag != null) switch (e.key) { case "Escape": this.splitter.element .releasePointerCapture(this.drag.pointerId); this.setValue(this.drag.value); this.drag = null; break; default: return; } // No drag is in progress else switch (e.key) { // Arrow keys case "ArrowDown": if (!args.horizontal) return; this.setValue(args.value + this.increment * (this.edge == SplitPane.TOP ? 1 : -1)); break; case "ArrowLeft": if (args.horizontal) return; this.setValue(args.value + this.increment * (this.edge == SplitPane.LEFT ? -1 : 1)); break; case "ArrowRight": if (args.horizontal) return; this.setValue(args.value + this.increment * (this.edge == SplitPane.LEFT ? 1 : -1)); break; case "ArrowUp": if (!args.horizontal) return; this.setValue(args.value + this.increment * (this.edge == SplitPane.TOP ? -1 : 1)); break; // Extent keys case "End": this.setValue( this.edge == SplitPane.TOP || this.edge == SplitPane.LEFT ? args.max : 0 ); break; case "Home": this.setValue( this.edge == SplitPane.TOP || this.edge == SplitPane.LEFT ? 0 : args.max ); break; // Miscellaneous case "Enter": if (this.collapsed === null) { this.setValue(0); this.collapsed = args.value; } else this.setValue(this.collapsed); break; default: return; } // Configure event e.stopPropagation(); e.preventDefault(); } // Pointer down onPointerDown(e) { this.splitter.focus(); // Error checking if (this.splitter.element.hasPointerCapture(e.pointerId)||e.button!=0) return; // Configure event this.splitter.element.setPointerCapture(e.pointerId); e.stopPropagation(); e.preventDefault(); // Record pointer parameters this.drag = this.getArgs(); Object.assign(this.drag, { pointerId: e.pointerId, primary : this[this.drag.primary], property : this.drag.horizontal ? "height" : "width", x : e.screenX / devicePixelRatio, y : e.screenY / devicePixelRatio }); } // Pointer move onPointerMove(e) { // Error checking if (!this.splitter.element.hasPointerCapture(e.pointerId)) return; // Configure event e.stopPropagation(); e.preventDefault(); // Update splitter position let coord=e[this.drag.horizontal?"screenY":"screenX"]/devicePixelRatio; let value = this.drag.value; switch (this.edge) { case SplitPane.BOTTOM: value += this.drag.y - coord; break; case SplitPane.LEFT : value += coord - this.drag.x; break; case SplitPane.RIGHT : value += this.drag.x - coord; break; case SplitPane.TOP : value += coord - this.drag.y; break; } this.setValue(value); } // Pointer up onPointerUp(e) { // Error checking if (!this.splitter.element.hasPointerCapture(e.pointerId)||e.button!=0) return; // Configure event this.splitter.element.releasePointerCapture(e.pointerId); e.stopPropagation(); e.preventDefault(); // Configure instance fields this.drag = null; } ///////////////////////////// Public Methods ////////////////////////////// // Retrieve the current position getValue() { return this.getArgs().value; } // Specify which edge is controlled by the splitter setEdge(edge) { // Error checking let args = this.getArgs(edge); if (args == null) return; // Configure instance fields this.edge = edge; // Configure elements let pri = this[args.primary ].style; let sec = this[args.primary ^ 1].style; this.element.style.flexDirection = args.horizontal ? "column" : "row"; this.splitter.setAttribute("aria-orientation", args.horizontal ? "horizontal" : "vertical"); pri.removeProperty("flex-grow"); pri.removeProperty("height" ); pri.removeProperty("width" ); sec.flexGrow = "1"; sec.removeProperty("height" ); sec.removeProperty("width" ); this.measure(); } // Specify how many pixels to change for an arrow key press setIncrement(increment) { if (typeof increment == "number" && !isNaN(increment)) this.increment = Math.max(1, Math.round(increment)); } // Specify the position of the splitter setValue(value, args) { args = args || this.getArgs(); this[args.primary].style[args.horizontal ? "height" : "width"] = Math.min(args.max, Math.max(0, Math.round(value))) + "px"; this.collapsed = null; this.measure(); } // Specify a child element setView(index, view, noMeasure) { index = this[index]; // Error checking if (view == index.view) return; // Remove the previous view if (index.view != null) { if (Toolkit.isComponent(index.view)) { index.view.parent = null; index.view.element.remove; } else index.view.remove(); } // Error checking if (!(view instanceof Element || Toolkit.isComponent(view))) view = null; // Configure instance fields index.view = view; // Associate the new view if (view != null) { index.append(view instanceof Element ? view : view.element); if (Toolkit.isComponent(view)) view.parent = this; } // Update elements if (!noMeasure) this.measure(); } ///////////////////////////// Private Methods ///////////////////////////// // Determine information regarding the current element configuration getArgs(edge = this.edge) { let bndA = this[0].getBoundingClientRect(); let bndB = this[1].getBoundingClientRect(); // Processing by edge let horizontal; let primary; switch (edge) { case SplitPane.BOTTOM: horizontal = true ; primary = 1; break; case SplitPane.LEFT : horizontal = false; primary = 0; break; case SplitPane.RIGHT : horizontal = false; primary = 1; break; case SplitPane.TOP : horizontal = true ; primary = 0; break; default: return null; } // Processing by orientation let bndPrimary = primary ? bndB : bndA; let max; let value; if (horizontal) { max = bndA.height + bndB.height; value = bndPrimary.height; } else { max = bndA.width + bndB.width; value = bndPrimary.width; } return { horizontal: horizontal, max : Math.round(max), primary : primary, value : Math.round(value) }; } // Measure the current element configuration measure() { let args = this.getArgs(); this.splitter.setAttribute("aria-valuemax", args.max); this.splitter.setAttribute("aria-valuemin", 0); this.splitter.setAttribute("aria-valuenow", args.value); } } export { ScrollBar, ScrollPane, SplitPane };