208 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			208 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import Theme from './theme.js'
 | 
						|
import { InteractivePopup } from './popup.js'
 | 
						|
 | 
						|
/**
 | 
						|
 * Class that represents a PixiJS Modal.
 | 
						|
 *
 | 
						|
 * @example
 | 
						|
 * // Create the button and the modal when clicked
 | 
						|
 * const button = new Button({
 | 
						|
 *     label: 'Show Modal',
 | 
						|
 *     action: e => {
 | 
						|
 *         const modal = new Modal({
 | 
						|
 *             app: app,
 | 
						|
 *             header: 'This is the header',
 | 
						|
 *             content: 'This is the text.'
 | 
						|
 *         })
 | 
						|
 *         app.scene.addChild(modal)
 | 
						|
 *     }
 | 
						|
 * })
 | 
						|
 *
 | 
						|
 * // Add the button to a DisplayObject
 | 
						|
 * app.scene.addChild(button)
 | 
						|
 *
 | 
						|
 * @class
 | 
						|
 * @extends PIXI.Container
 | 
						|
 * @extends InteractivePopup
 | 
						|
 * @see {@link http://pixijs.download/dev/docs/PIXI.Container.html|PIXI.Container}
 | 
						|
 * @see {@link https://www.iwm-tuebingen.de/iwmbrowser/lib/pixi/modal.html|DocTest}
 | 
						|
 */
 | 
						|
export default class Modal extends PIXI.Container {
 | 
						|
    /**
 | 
						|
     * Creates an instance of a Modal.
 | 
						|
     *
 | 
						|
     * @constructor
 | 
						|
     * @param {object} [opts] - An options object to specify to style and behaviour of the modal.
 | 
						|
     * @param {number} [opts.id=auto generated] - The id of the modal.
 | 
						|
     * @param {PIXIApp} [opts.app=window.app] - The app where the modal belongs to.
 | 
						|
     * @param {number} [opts.backgroundFill=Theme.background] - The color of the background.
 | 
						|
     * @param {number} [opts.backgroundFillAlpha=0.6] - The opacity of the background.
 | 
						|
     * @param {boolean} [opts.closeOnBackground=true] - Should the modal be closed when the user clicks the
 | 
						|
     *     background?
 | 
						|
     * @param {boolean} [opts.visible=true] - Is the modal initially visible (property visible)?
 | 
						|
     */
 | 
						|
    constructor(opts = {}) {
 | 
						|
        super()
 | 
						|
 | 
						|
        const theme = Theme.fromString(opts.theme)
 | 
						|
        this.theme = theme
 | 
						|
 | 
						|
        this.opts = Object.assign(
 | 
						|
            {},
 | 
						|
            {
 | 
						|
                id: PIXI.utils.uid(),
 | 
						|
                app: window.app,
 | 
						|
                backgroundFill: theme.background,
 | 
						|
                backgroundFillAlpha: 0.6,
 | 
						|
                closeOnBackground: true,
 | 
						|
                visible: true,
 | 
						|
            },
 | 
						|
            opts
 | 
						|
        )
 | 
						|
 | 
						|
        this.id = this.opts.id
 | 
						|
 | 
						|
        this.background = null
 | 
						|
        this.popup = null
 | 
						|
 | 
						|
        this.alpha = 0
 | 
						|
        this.visible = this.opts.visible
 | 
						|
 | 
						|
        // setup
 | 
						|
        //-----------------
 | 
						|
        this.setup()
 | 
						|
 | 
						|
        // layout
 | 
						|
        //-----------------
 | 
						|
        this.layout()
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Creates children and instantiates everything.
 | 
						|
     *
 | 
						|
     * @private
 | 
						|
     * @return {Modal} A reference to the modal for chaining.
 | 
						|
     */
 | 
						|
    setup() {
 | 
						|
        // interaction
 | 
						|
        //-----------------
 | 
						|
        this.interactive = true
 | 
						|
        this.on('added', (e) => {
 | 
						|
            if (this.visible) {
 | 
						|
                this.show()
 | 
						|
            }
 | 
						|
        })
 | 
						|
 | 
						|
        // background
 | 
						|
        //-----------------
 | 
						|
        let background = new PIXI.Graphics()
 | 
						|
        this.background = background
 | 
						|
        this.addChild(this.background)
 | 
						|
 | 
						|
        if (this.opts.closeOnBackground) {
 | 
						|
            background.interactive = true
 | 
						|
            background.on('pointerup', (e) => {
 | 
						|
                this.hide()
 | 
						|
            })
 | 
						|
        }
 | 
						|
 | 
						|
        // popup
 | 
						|
        //-----------------
 | 
						|
        const popupOpts = Object.assign({}, this.opts, {
 | 
						|
            visible: true,
 | 
						|
            onHidden: () => {
 | 
						|
                this.hide()
 | 
						|
            },
 | 
						|
        })
 | 
						|
        let popup = new InteractivePopup(popupOpts)
 | 
						|
        this.popup = popup
 | 
						|
        this.addChild(popup)
 | 
						|
        popup.show()
 | 
						|
 | 
						|
        return this
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Should be called to refresh the layout of the modal. Can be used after resizing.
 | 
						|
     *
 | 
						|
     * @return {Modal} A reference to the modal for chaining.
 | 
						|
     */
 | 
						|
    layout() {
 | 
						|
        const width = this.opts.app.size.width
 | 
						|
        const height = this.opts.app.size.height
 | 
						|
 | 
						|
        // background
 | 
						|
        //-----------------
 | 
						|
        this.background.clear()
 | 
						|
        this.background.beginFill(this.opts.backgroundFill, this.opts.backgroundFillAlpha)
 | 
						|
        this.background.drawRect(0, 0, width, height)
 | 
						|
        this.background.endFill()
 | 
						|
 | 
						|
        // position
 | 
						|
        this.popup.x = width / 2 - this.popup.width / 2
 | 
						|
        this.popup.y = height / 2 - this.popup.height / 2
 | 
						|
 | 
						|
        return this
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Shows the modal (sets his alpha values to 1).
 | 
						|
     *
 | 
						|
     * @return {Modal} A reference to the modal for chaining.
 | 
						|
     */
 | 
						|
    show() {
 | 
						|
        TweenLite.to(this, this.theme.fast, {
 | 
						|
            alpha: 1,
 | 
						|
            onStart: () => (this.visible = true),
 | 
						|
        })
 | 
						|
 | 
						|
        return this
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Hides the modal (sets his alpha values to 0).
 | 
						|
     *
 | 
						|
     * @return {Modal} A reference to the modal for chaining.
 | 
						|
     */
 | 
						|
    hide() {
 | 
						|
        TweenLite.to(this, this.theme.fast, {
 | 
						|
            alpha: 0,
 | 
						|
            onComplete: () => (this.visible = false),
 | 
						|
        })
 | 
						|
 | 
						|
        return this
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Sets or gets the header. The getter always returns a PIXI.Text object. The setter can receive
 | 
						|
     * a string or a PIXI.Text object.
 | 
						|
     *
 | 
						|
     * @member {string|PIXI.Text}
 | 
						|
     */
 | 
						|
    get header() {
 | 
						|
        return this.popup.header
 | 
						|
    }
 | 
						|
    set header(value) {
 | 
						|
        this.opts.header = value
 | 
						|
        this.background.destroy()
 | 
						|
        this.popup.destroy()
 | 
						|
        this.setup().layout()
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Sets or gets the content. The getter always returns an PIXI.DisplayObject. The setter can receive
 | 
						|
     * a string or a PIXI.DisplayObject.
 | 
						|
     *
 | 
						|
     * @member {string|PIXI.DisplayObject}
 | 
						|
     */
 | 
						|
    get content() {
 | 
						|
        return this.popup.content
 | 
						|
    }
 | 
						|
    set content(value) {
 | 
						|
        this.opts.content = value
 | 
						|
        this.background.destroy()
 | 
						|
        this.popup.destroy()
 | 
						|
        this.setup().layout()
 | 
						|
    }
 | 
						|
}
 |