JavaScript Extension Development API for Oracle Visual Builder Cloud Service - Classic Applications

Source: components.dt/js/spi/creators/PopupCreator.js

define([
    'components.dt/js/spi/creators/Creator',
    'components.dt/js/spi/creators/CreatorType'
], function (
    Creator,
    CreatorType
    ) {

    'use strict';

    /**
     * Interface describing a lightweight Popup Creator raising a popup window
     * right after a view is created and added to a page, intended to modify
     * the view's properties before the create process finishes.
     *
     * <p>Interface for creators that show a popup for entering basic component
     * properties (data binding, type, field name, label) when new component is to
     * be created.</p>
     *
     * <p>The infrastructure first calls {@link components.dt/js/spi/creators/PopupCreator#createView createView}
     * to create a view with default state and properties. When the view is created
     * and added to the page {@link components.dt/js/spi/creators/PopupCreator#getDropPopupController getDropPopupController}
     * is called to obtain a {@link components.dt/js/spi/creators/DropPopupController DropPopupController}
     * instance. The infrastructure finally raises a popup with data provided by
     * the returned DropPopupController. It's up to the implementor to ensure
     * the view is properly updated with any modifications done inside the popup.</p>
     *
     * <p>Even though ABCS by default raises a popup to customize the created
     * view, the creator may be called through the {@link components.dt/js/api/ComponentFactory Creator API}
     * by other creators to include the view into their own composed view hierarchy
     * in which case the popup will not be opened and the creator ({@link components.dt/js/spi/creators/PopupCreator#createView createView})
     * is obliged to return a full working view based on the passed <code>createContext</code>
     * containing the default properties. See the example below for demonstation.</p>
     *
     * <p>You are obliged to implement:</p>
     * <ul>
     * <li>{@link components.dt/js/spi/creators/PopupCreator#createView createView}
     * to create the default view. The returned view should be as complete as
     * possible as the method may be called through the {@link components.dt/js/api/ComponentFactory Creator API} by other creators
     * without the popup even being raised.</li>
     * <li>{@link components.dt/js/spi/creators/PopupCreator#getDropPopupController getDropPopupController}
     * to return an instance of {@link components.dt/js/spi/creators/DropPopupController DropPopupController}
     * providing the popup's view model, HTML markup and {@link components.dt/js/spi/creators/DropPopupController.DropCustomizer DropCustomizer}
     * instance.</li>
     * <li>{@link components.dt/js/spi/creators/PopupCreator#getType getType} to
     * specify the creator is a popup creator</li>
     * </ul>
     *
     * @AbcsExtension stable
     * @version 16.3.5
     * @exports components.dt/js/spi/creators/PopupCreator
     * @augments components.dt/js/spi/creators/Creator
     * @constructor
     * @private
     * @example
     * <caption>HTML markup for the popup</caption>
     * <div>
     *   <label for="componentdropCustomizer-label">Text</label>
     *   <input id="componentdropCustomizer-label" type="text"
     *       placeholder="Enter Text" data-bind="ojComponent: {
     *           component: 'ojInputText',
     *           value: text
     *   }">
     * </div>
     * <div>
     *   <button data-bind="ojComponent: {
     *       component: 'ojButton',
     *       label: 'Finish'
     *   }, click: finish">
     *   </button>
     *   <button data-bind="ojComponent: {
     *       component: 'ojButton',
     *       label: 'Cancel'
     *   }, click: cancel">
     *   </button>
     * </div>
     * @example
     * <caption>How to use popup creators</caption>
     * define([
     *     'components.dt/js/spi/creators/CreatorType'
     *     'components.dt/js/spi/creators/DropPopupController',
     *     'text!mycomponent/templates/popup.html
     * ], function (CreatorType, DropPopupController, popupMarkup) {
     *
     *     'use strict';
     *
     *     var MyCreator = function () {
     *         // constructor init
     *     };
     *
     *     MyCreator.prototype.getType = function () {
     *         return CreatorType.POPUP;
     *     };
     *
     *     MyCreator.prototype.createView = function (activePage, container, createContext) {
     *         // the method creates a default view with default properties.
     *         var componentFactory = ComponentFactory.create(activePage);
     *         // set the default view's property value
     *         var properties = {
     *             text: 'Default Text'
     *         };
     *
     *         // the method should take createContext into account and fill as
     *         // many properties as possible to make the view complete because
     *         // when called through the Component Creator API the popup will
     *         // not be raised.
     *         if (createContext && createContext.text) {
     *             properties.text = createContext.text;
     *         }
     *
     *         var view = componentFactory.createView({
     *             type: 'org.my.myComponent',
     *             properties: properties,
     *             displayName: 'My Component'
     *         });
     *         return view;
     *     };
     *
     *     MyCreator.prototype.getDropPopupController = function (view) {
     *         // right after the view is created the infrastructure calls this method
     *         // to get an instance of DropPopupController providing the html markup,
     *         // view model and the callback implementation for the popup.
     *         var myPopupViewModel = this._createModel();
     *         var customizer = new MyCreator.MyDropCustomizer(view, myPopupViewModel);
     *
     *         // create an instance of DropPopupController with required popup model and markup.
     *         var controller = new DropPopupController(myPopupViewModel, popupMarkup, customizer);
     *
     *         // attach a finish handler to your model and dismiss the popup
     *         // when the model says so using an API finish method.
     *         myPopupViewModel.finishHandler = function (result) {
     *             controller.finish(result);
     *         };
     *         return controller;
     *     };
     *
     *     MyCreator.prototype._createModel = function () {
     *         var model = {
     *             text: ko.observable(),
     *             finishHandler: undefined,
     *             finish: function () {
     *                 this.finishHandler(true);
     *             },
     *             cancel: function () {
     *                 this.finishHandler(false);
     *             }
     *         };
     *         return model;
     *     };
     *
     *     MyCreator.prototype.getOptions = function () {
     *         return {
     *             // the creator is expected to create only one type of view: org.my.myComponent
     *             possibleGeneratedViewTypes: ['org.my.myComponent'],
     *             // min width of the component will be 2 columns
     *             minWidth: 2
     *         };
     *     };
     *
     *     var MyDropCustomizer = function (view, model) {
     *         this._view = view;
     *         this._model = model;
     *     };
     *
     *     MyDropCustomizer.prototype.opened = function () {
     *         // you can do something useful here
     *     };
     *
     *     MyDropCustomizer.prototype.closed = function (accepted) {
     *         if (accepted) {
     *             // popup was accepted and closed, let's update view properties
     *             this._view.getProperties().setValue('text', this._model.text());
     *         }
     *         // do not forget to return a promise resolving to the view instance
     *         return Promise.resolve(this._view);
     *     };
     *
     *     MyCreator.MyDropCustomizer = MyDropCustomizer;
     *
     *     return MyCreator;
     *
     * });
     *
     */
    var PopupCreator = function () {
        AbcsLib.checkThis(this);
        Creator.call(this);
    };

    AbcsLib.extend(PopupCreator, Creator);

    /**
     * Specifies the type of the creator.
     * <p>Popup creators must return {@link components.dt/js/spi/creators/CreatorType.POPUP CreatorType.POPUP}
     * type.</p>
     *
     * @AbcsExtension stable
     * @version 16.3.5
     * @overrides
     * @returns {components.dt/js/spi/creators/CreatorType} creator type
     */
    PopupCreator.prototype.getType = function () {
        return CreatorType.POPUP;
    };

    /**
     * Creates and returns a {@link components.dt/js/spi/creators/DropPopupController DropPopupController}
     * instance for the PopupCreator implementation. DropPopupController is a class
     * controlling the behavior of the opened popup modyfying the created view's
     * properties during the view create process. See {@link components.dt/js/spi/creators/PopupCreator PopupCreator}
     * for an example on how to implement this method.
     *
     * <p><strong>Must</strong> be overridden and implemented in descendants.
     *
     * @AbcsExtension stable
     * @version 16.3.5
     * @param {pages.dt/js/api/View} view created view to be customized.
     * @returns {components.dt/js/spi/creators/DropPopupController} DropPopupController instance
     */
    PopupCreator.prototype.getDropPopupController = function (/*view*/) {
        throw new Error('getDropPopupController() must be implemented.');
    };

    /**
     * Override to specify any special open options for the drop customizer.
     * @returns {Object} object with options
     */
    PopupCreator.prototype.getDropCustomizerOpenOptions = function () {
        return {};
    };

    return PopupCreator;
});