UNPKG

infusion

Version:

Infusion is an application framework for developing flexible stuff with JavaScript

170 lines (153 loc) 5.78 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"; fluid.registerNamespace("fluid.undo"); // The three states of the undo component fluid.undo.STATE_INITIAL = "state_initial"; fluid.undo.STATE_CHANGED = "state_changed"; fluid.undo.STATE_REVERTED = "state_reverted"; fluid.undo.defaultRenderer = function (that, targetContainer) { var str = that.options.strings; var markup = "<span class='flc-undo'>" + "<a href='#' class='flc-undo-undoControl'>" + str.undo + "</a>" + "<a href='#' class='flc-undo-redoControl'>" + str.redo + "</a>" + "</span>"; var markupNode = $(markup).attr({ "role": "region", "aria-live": "polite", "aria-relevant": "all" }); targetContainer.append(markupNode); return markupNode; }; fluid.undo.refreshView = function (that) { if (that.state === fluid.undo.STATE_INITIAL) { that.locate("undoContainer").hide(); that.locate("redoContainer").hide(); } else if (that.state === fluid.undo.STATE_CHANGED) { that.locate("undoContainer").show(); that.locate("redoContainer").hide(); } else if (that.state === fluid.undo.STATE_REVERTED) { that.locate("undoContainer").hide(); that.locate("redoContainer").show(); } }; fluid.undo.undoControlClick = function (that) { if (that.state !== fluid.undo.STATE_REVERTED) { fluid.model.copyModel(that.extremalModel, that.component.model); that.component.updateModel(that.initialModel, that); that.state = fluid.undo.STATE_REVERTED; fluid.undo.refreshView(that); that.locate("redoControl").trigger("focus"); } return false; }; fluid.undo.redoControlClick = function (that) { if (that.state !== fluid.undo.STATE_CHANGED) { that.component.updateModel(that.extremalModel, that); that.state = fluid.undo.STATE_CHANGED; fluid.undo.refreshView(that); that.locate("undoControl").trigger("focus"); } return false; }; fluid.undo.modelChanged = function (that, newModel, oldModel, source) { if (source !== that) { that.state = fluid.undo.STATE_CHANGED; fluid.model.copyModel(that.initialModel, oldModel); fluid.undo.refreshView(that); } }; fluid.undo.copyInitialModel = function (that) { fluid.model.copyModel(that.initialModel, that.component.model); fluid.model.copyModel(that.extremalModel, that.component.model); }; fluid.undo.setTabindex = function (that) { fluid.tabindex(that.locate("undoControl"), 0); fluid.tabindex(that.locate("redoControl"), 0); }; /** * Decorates a target component with the function of "undoability". This component is intended to be attached as a * subcomponent to the target component, which will bear a grade of "fluid.undoable" * * @param {Object} component - a "model-bearing" standard Fluid component to receive the "undo" functionality * @param {Object} options - (optional) a collection of options settings */ fluid.defaults("fluid.undo", { gradeNames: ["fluid.viewComponent"], members: { state: fluid.undo.STATE_INITIAL, initialModel: {}, extremalModel: {}, component: "{fluid.undoable}", container: { expander: { func: "{that}.options.renderer", args: ["{that}", "{that}.component.container"] } } }, invokers: { undoControlClick: { funcName: "fluid.undo.undoControlClick", args: "{that}" }, redoControlClick: { funcName: "fluid.undo.redoControlClick", args: "{that}" } }, listeners: { "onCreate.copyInitialModel": { funcName: "fluid.undo.copyInitialModel", priority: "before:refreshView" }, "onCreate.setTabindex": "fluid.undo.setTabindex", "onCreate.refreshView": "fluid.undo.refreshView", "onCreate.bindUndoClick": { "this": "{that}.dom.undoControl", method: "on", args: ["click", "{that}.undoControlClick"] }, "onCreate.bindRedoClick": { "this": "{that}.dom.redoControl", method: "on", args: ["click", "{that}.redoControlClick"] }, "{fluid.undoable}.events.modelChanged": { funcName: "fluid.undo.modelChanged", args: ["{that}", "{arguments}.0", "{arguments}.1", "{arguments}.2"] } }, selectors: { undoContainer: ".flc-undo-undoControl", undoControl: ".flc-undo-undoControl", redoContainer: ".flc-undo-redoControl", redoControl: ".flc-undo-redoControl" }, strings: { undo: "undo edit", redo: "redo edit" }, renderer: fluid.undo.defaultRenderer }); // An uninstantiable grade expressing the contract of the "fluid.undoable" grade // WARNING: Note that the only component which complies with this "corrupt contract" of being a fluid.modelComponent but // having an unrelated means of updating the model is fluid.inlineEdit - it should not be used. fluid.defaults("fluid.undoable", { gradeNames: ["fluid.modelComponent"], invokers: { updateModel: {} // will be implemented by concrete grades }, events: { modelChanged: null } });