UNPKG

infusion

Version:

Infusion is an application framework for developing flexible stuff with JavaScript

159 lines (147 loc) 6.17 kB
/* Copyright The Infusion copyright holders See the AUTHORS.md file at the top-level directory of this distribution and at https://github.com/fluid-project/infusion/raw/main/AUTHORS.md. Licensed under the Educational Community License (ECL), Version 2.0 or the New BSD license. You may not use this file except in compliance with one these Licenses. You may obtain a copy of the ECL 2.0 License and BSD License at https://github.com/fluid-project/infusion/raw/main/Infusion-LICENSE.txt */ "use strict"; /************************************************************************************ * Scrolling Panel Prefs Editor: * * This is a mixin grade to be applied to a fluid.prefs.prefsEditor type component. * * Typically used for responsive small screen presentations of the separated panel * * to allow for scrolling by clicking on left/right arrows * ************************************************************************************/ fluid.defaults("fluid.prefs.arrowScrolling", { gradeNames: ["fluid.modelComponent"], selectors: { // panels: "", // should be supplied by the fluid.prefs.prefsEditor grade. scrollContainer: ".flc-prefsEditor-scrollContainer" }, onScrollDelay: 100, // in ms, used to set the delay for debouncing the scroll event relay model: { // panelMaxIndex: null, // determined by the number of panels calculated after the onPrefsEditorMarkupReady event fired // Due to FLUID-6249 ( https://issues.fluidproject.org/browse/FLUID-6249 ) the default value for panelIndex // needs to be commented out or it will interfere with reading in the panelIndex value saved in the store. // panelIndex: 0 // the index of the panel to open on }, events: { beforeReset: null, // should be fired by the fluid.prefs.prefsEditor grade onScroll: null }, modelRelay: { target: "panelIndex", forward: {excludeSource: "init"}, namespace: "limitPanelIndex", singleTransform: { type: "fluid.transforms.limitRange", input: "{that}.model.panelIndex", min: 0, max: "{that}.model.panelMaxIndex" } }, modelListeners: { "panelIndex": { listener: "fluid.prefs.arrowScrolling.scrollToPanel", args: ["{that}", "{change}.value"], excludeSource: ["scrollEvent"], namespace: "scrollToPanel" } }, listeners: { "onReady.scrollEvent": { "this": "{that}.dom.scrollContainer", method: "on", args: [ "scroll", { expander: { // Relaying the scroll event to onScroll but debounced to reduce the rate of fire. A high rate // of fire may negatively effect performance for complex handlers. func: "fluid.debounce", args: ["{that}.events.onScroll.fire", "{that}.options.onScrollDelay"] } } ] }, // Need to set panelMaxIndex after onPrefsEditorMarkupReady to ensure that the template has been // rendered before we try to get the number of panels. "onPrefsEditorMarkupReady.setPanelMaxIndex": { changePath: "panelMaxIndex", value: { expander: { funcName: "fluid.prefs.arrowScrolling.calculatePanelMaxIndex", args: ["{that}.dom.panels"] } } }, "beforeReset.resetPanelIndex": { listener: "{that}.applier.fireChangeRequest", args: {path: "panelIndex", value: 0, type: "ADD", source: "reset"} }, "onScroll.setPanelIndex": { changePath: "panelIndex", value: { expander: { funcName: "fluid.prefs.arrowScrolling.getClosestPanelIndex", args: "{that}.dom.panels" } }, source: "scrollEvent" } }, invokers: { eventToScrollIndex: { funcName: "fluid.prefs.arrowScrolling.eventToScrollIndex", args: ["{that}", "{arguments}.0"] } }, distributeOptions: { "arrowScrolling.panel.listeners.bindScrollArrows": { record: { "afterRender.bindScrollArrows": { "this": "{that}.dom.header", method: "on", args: ["click", "{prefsEditor}.eventToScrollIndex"] } }, target: "{that > fluid.prefs.panel}.options.listeners" } } }); fluid.prefs.arrowScrolling.calculatePanelMaxIndex = function (panels) { return Math.max(0, panels.length - 1); }; fluid.prefs.arrowScrolling.eventToScrollIndex = function (that, event) { event.preventDefault(); var target = $(event.target); var midPoint = target.width() / 2; var currentIndex = that.model.panelIndex || 0; var scrollToIndex = currentIndex + (event.offsetX < midPoint ? -1 : 1); that.applier.change("panelIndex", scrollToIndex, "ADD", "eventToScrollIndex"); }; fluid.prefs.arrowScrolling.scrollToPanel = function (that, panelIndex) { panelIndex = panelIndex || 0; var panels = that.locate("panels"); var scrollContainer = that.locate("scrollContainer"); var panel = panels.eq(panelIndex); // only attempt to scroll the container if the panel exists and has been rendered. if (panel.width()) { scrollContainer.scrollLeft(scrollContainer.scrollLeft() + panels.eq(panelIndex).offset().left); } }; fluid.prefs.arrowScrolling.getClosestPanelIndex = function (panels) { var panelArray = fluid.transform(panels, function (panel, idx) { return { index: idx, offset: Math.abs($(panel).offset().left) }; }); panelArray.sort(function (a, b) { return a.offset - b.offset; }); return fluid.get(panelArray, ["0", "index"]) || 0; };