UNPKG

@qooxdoo/framework

Version:

The JS Framework for Coders

510 lines (422 loc) 13 kB
/* ************************************************************************ qooxdoo - the new era of web development http://qooxdoo.org Copyright: 2004-2008 1&1 Internet AG, Germany, http://www.1und1.de License: MIT: https://opensource.org/licenses/MIT See the LICENSE file in the project's top-level directory for details. Authors: * Sebastian Werner (wpbasti) * Fabian Jakobs (fjakobs) * Jonathan Weiß (jonathan_rass) ************************************************************************ */ /** * Container, which provides scrolling in one dimension (vertical or horizontal). * * @childControl button-forward {qx.ui.form.RepeatButton} button to step forward * @childControl button-backward {qx.ui.form.RepeatButton} button to step backward * @childControl content {qx.ui.container.Composite} container to hold the content * @childControl scrollpane {qx.ui.core.scroll.ScrollPane} the scroll pane holds the content to enable scrolling * * *Example* * * Here is a little example of how to use the widget. * * <pre class='javascript'> * // create slide bar container * slideBar = new qx.ui.container.SlideBar().set({ * width: 300 * }); * * // set layout * slideBar.setLayout(new qx.ui.layout.HBox()); * * // add some widgets * for (var i=0; i<10; i++) * { * slideBar.add((new qx.ui.core.Widget()).set({ * backgroundColor : (i % 2 == 0) ? "red" : "blue", * width : 60 * })); * } * * this.getRoot().add(slideBar); * </pre> * * This example creates a SlideBar and add some widgets with alternating * background colors. Since the content is larger than the container, two * scroll buttons at the left and the right edge are shown. * * *External Documentation* * * <a href='http://manual.qooxdoo.org/${qxversion}/pages/widget/slidebar.html' target='_blank'> * Documentation of this widget in the qooxdoo manual.</a> */ qx.Class.define("qx.ui.container.SlideBar", { extend : qx.ui.core.Widget, include : [ qx.ui.core.MRemoteChildrenHandling, qx.ui.core.MRemoteLayoutHandling ], /* ***************************************************************************** CONSTRUCTOR ***************************************************************************** */ /** * @param orientation {String?"horizontal"} The slide bar orientation */ construct : function(orientation) { this.base(arguments); var scrollPane = this.getChildControl("scrollpane"); this._add(scrollPane, {flex: 1}); if (orientation != null) { this.setOrientation(orientation); } else { this.initOrientation(); } this.addListener("roll", this._onRoll, this); }, /* ***************************************************************************** PROPERTIES ***************************************************************************** */ properties : { // overridden appearance : { refine : true, init : "slidebar" }, /** Orientation of the bar */ orientation : { check : ["horizontal", "vertical"], init : "horizontal", apply : "_applyOrientation" }, /** The number of pixels to scroll if the buttons are pressed */ scrollStep : { check : "Integer", init : 15, themeable : true } }, /* ***************************************************************************** EVENTS ***************************************************************************** */ events : { /** Fired on scroll animation end invoked by 'scroll*' methods. */ scrollAnimationEnd : "qx.event.type.Event" }, /* ***************************************************************************** MEMBERS ***************************************************************************** */ members : { /* --------------------------------------------------------------------------- WIDGET API --------------------------------------------------------------------------- */ // overridden getChildrenContainer : function() { return this.getChildControl("content"); }, // overridden _createChildControlImpl : function(id, hash) { var control; switch(id) { case "button-forward": control = new qx.ui.form.RepeatButton; control.addListener("execute", this._onExecuteForward, this); control.setFocusable(false); this._addAt(control, 2); break; case "button-backward": control = new qx.ui.form.RepeatButton; control.addListener("execute", this._onExecuteBackward, this); control.setFocusable(false); this._addAt(control, 0); break; case "content": control = new qx.ui.container.Composite(); this.getChildControl("scrollpane").add(control); break; case "scrollpane": control = new qx.ui.core.scroll.ScrollPane(); control.addListener("update", this._onResize, this); control.addListener("scrollX", this._onScroll, this); control.addListener("scrollY", this._onScroll, this); control.addListener("scrollAnimationEnd", this._onScrollAnimationEnd, this); break; } return control || this.base(arguments, id); }, // overridden /** * @lint ignoreReferenceField(_forwardStates) */ _forwardStates : { barLeft : true, barTop : true, barRight : true, barBottom : true }, /* --------------------------------------------------------------------------- PUBLIC SCROLL API --------------------------------------------------------------------------- */ /** * Scrolls the element's content by the given amount. * * @param offset {Integer?0} Amount to scroll * @param duration {Number?} The time in milliseconds the scroll to should take. */ scrollBy : function(offset, duration) { var pane = this.getChildControl("scrollpane"); if (this.getOrientation() === "horizontal") { pane.scrollByX(offset, duration); } else { pane.scrollByY(offset, duration); } }, /** * Scrolls the element's content to the given coordinate * * @param value {Integer} The position to scroll to. * @param duration {Number?} The time in milliseconds the scroll to should take. */ scrollTo : function(value, duration) { var pane = this.getChildControl("scrollpane"); if (this.getOrientation() === "horizontal") { pane.scrollToX(value, duration); } else { pane.scrollToY(value, duration); } }, /* --------------------------------------------------------------------------- PROPERTY APPLY ROUTINES --------------------------------------------------------------------------- */ // overridden _applyEnabled : function(value, old, name) { this.base(arguments, value, old, name); this._updateArrowsEnabled(); }, // property apply _applyOrientation : function(value, old) { var oldLayouts = [this.getLayout(), this._getLayout()]; var buttonForward = this.getChildControl("button-forward"); var buttonBackward = this.getChildControl("button-backward"); // old can also be null, so we have to check both explicitly to set // the states correctly. if (old == "vertical" && value == "horizontal") { buttonForward.removeState("vertical"); buttonBackward.removeState("vertical"); buttonForward.addState("horizontal"); buttonBackward.addState("horizontal"); } else if (old == "horizontal" && value == "vertical") { buttonForward.removeState("horizontal"); buttonBackward.removeState("horizontal"); buttonForward.addState("vertical"); buttonBackward.addState("vertical"); } if (value == "horizontal") { this._setLayout(new qx.ui.layout.HBox()); this.setLayout(new qx.ui.layout.HBox()); } else { this._setLayout(new qx.ui.layout.VBox()); this.setLayout(new qx.ui.layout.VBox()); } if (oldLayouts[0]) { oldLayouts[0].dispose(); } if (oldLayouts[1]) { oldLayouts[1].dispose(); } }, /* --------------------------------------------------------------------------- EVENT LISTENERS --------------------------------------------------------------------------- */ /** * Scrolls pane on roll events * * @param e {qx.event.type.Roll} the roll event */ _onRoll : function(e) { // only wheel and touch if (e.getPointerType() == "mouse") { return; } var delta = 0; var pane = this.getChildControl("scrollpane"); if (this.getOrientation() === "horizontal") { delta = e.getDelta().x; var position = pane.getScrollX(); var max = pane.getScrollMaxX(); var steps = parseInt(delta); // pass the event to the parent if both scrollbars are at the end if (!( steps < 0 && position <= 0 || steps > 0 && position >= max || delta == 0) ) { e.stop(); } else { e.stopMomentum(); } } else { delta = e.getDelta().y; var position = pane.getScrollY(); var max = pane.getScrollMaxY(); var steps = parseInt(delta); // pass the event to the parent if both scrollbars are at the end if (!( steps < 0 && position <= 0 || steps > 0 && position >= max || delta == 0 )) { e.stop(); } else { e.stopMomentum(); } } this.scrollBy(parseInt(delta, 10)); // block all momentum scrolling if (e.getMomentum()) { e.stop(); } }, /** * Update arrow enabled state after scrolling */ _onScroll : function() { this._updateArrowsEnabled(); }, /** * Handler to fire the 'scrollAnimationEnd' event. */ _onScrollAnimationEnd : function() { this.fireEvent("scrollAnimationEnd"); }, /** * Listener for resize event. This event is fired after the * first flush of the element which leads to another queuing * when the changes modify the visibility of the scroll buttons. * * @param e {Event} Event object */ _onResize : function(e) { var content = this.getChildControl("scrollpane").getChildren()[0]; if (!content) { return; } var innerSize = this.getInnerSize(); var contentSize = content.getBounds(); var overflow = (this.getOrientation() === "horizontal") ? contentSize.width > innerSize.width : contentSize.height > innerSize.height; if (overflow) { this._showArrows(); this._updateArrowsEnabled(); } else { this._hideArrows(); } }, /** * Scroll handler for left scrolling * */ _onExecuteBackward : function() { this.scrollBy(-this.getScrollStep()); }, /** * Scroll handler for right scrolling * */ _onExecuteForward : function() { this.scrollBy(this.getScrollStep()); }, /* --------------------------------------------------------------------------- UTILITIES --------------------------------------------------------------------------- */ /** * Update arrow enabled state */ _updateArrowsEnabled : function() { // set the disables state directly because we are overriding the // inheritance if (!this.getEnabled()) { this.getChildControl("button-backward").setEnabled(false); this.getChildControl("button-forward").setEnabled(false); return; } var pane = this.getChildControl("scrollpane"); if (this.getOrientation() === "horizontal") { var position = pane.getScrollX(); var max = pane.getScrollMaxX(); } else { var position = pane.getScrollY(); var max = pane.getScrollMaxY(); } this.getChildControl("button-backward").setEnabled(position > 0); this.getChildControl("button-forward").setEnabled(position < max); }, /** * Show the arrows (Called from resize event) * */ _showArrows : function() { this._showChildControl("button-forward"); this._showChildControl("button-backward"); }, /** * Hide the arrows (Called from resize event) * */ _hideArrows : function() { this._excludeChildControl("button-forward"); this._excludeChildControl("button-backward"); this.scrollTo(0); } } });