239 lines
7.4 KiB
JavaScript
239 lines
7.4 KiB
JavaScript
import AbstractPopup from './abstractpopup.js'
|
|
import Button from './button.js'
|
|
import ButtonGroup from './buttongroup.js'
|
|
|
|
/**
|
|
* Class that represents a PixiJS InteractivePopup.
|
|
* The class is used for various other Popup-like classes
|
|
* like Popup, Message...
|
|
*
|
|
* @class
|
|
* @abstract
|
|
* @extends AbstractPopup
|
|
*/
|
|
export class InteractivePopup extends AbstractPopup {
|
|
/**
|
|
* Creates an instance of an InteractivePopup (only for internal use).
|
|
*
|
|
* @constructor
|
|
* @param {object} [opts] - An options object to specify to style and behaviour of the popup.
|
|
* @param {boolean} [opts.closeOnPopup=false] - Should the popup be closed when the user clicks on the popup?
|
|
* @param {boolean|string} [opts.closeButton=true] - Should a close button be displayed on the upper right corner? Alternatively, a URL to the image can be specified.
|
|
* @param {object} [opts.button] - A Button object to be display on the lower right corner.
|
|
* @param {object} [opts.buttonGroup] - A ButtonGroup object to be displayed on the lower right corner.
|
|
*/
|
|
constructor(opts = {}) {
|
|
opts = Object.assign(
|
|
{},
|
|
{
|
|
closeOnPopup: false,
|
|
closeButton: true,
|
|
button: null,
|
|
buttonGroup: null,
|
|
},
|
|
opts
|
|
)
|
|
|
|
super(opts)
|
|
|
|
this._closeButton = null
|
|
this._buttons = null
|
|
|
|
// padding
|
|
this.smallPadding = this.opts.padding / 2
|
|
|
|
// setup
|
|
//-----------------
|
|
this.setup()
|
|
|
|
// layout
|
|
//-----------------
|
|
this.layout()
|
|
}
|
|
|
|
/**
|
|
* Creates the framework and instantiates everything.
|
|
*
|
|
* @private
|
|
* @return {AbstractPopup} A reference to the popup for chaining.
|
|
*/
|
|
setup() {
|
|
super.setup()
|
|
|
|
// interaction
|
|
//-----------------
|
|
this.on('pointerup', (e) => {
|
|
if (this.opts.closeOnPopup) {
|
|
this.hide()
|
|
} else {
|
|
e.stopPropagation()
|
|
}
|
|
})
|
|
|
|
// closeButton
|
|
//-----------------
|
|
if (this.opts.closeButton) {
|
|
let url = null
|
|
if (typeof this.opts.closeButton === 'string' || this.opts.closeButton instanceof String) {
|
|
url = InteractivePopup.iconIsUrl(this.opts.closeButton)
|
|
? this.opts.closeButton
|
|
: `../../assets/icons/${this.opts.closeButton}.png`
|
|
} else {
|
|
url = '../../assets/icons/close.png'
|
|
}
|
|
|
|
let closeButton = PIXI.Sprite.from(url)
|
|
closeButton.width = this.headerStyle.fontSize
|
|
closeButton.height = closeButton.width
|
|
closeButton.tint = this.theme.color2
|
|
// This is needed, because the closeButton belongs to the content. The popup must resize with the closeButton.
|
|
if (this._header) {
|
|
closeButton.x = this._header.width + this.innerPadding
|
|
} else if (this._content) {
|
|
closeButton.x = this._content.width + this.innerPadding
|
|
}
|
|
|
|
closeButton.interactive = true
|
|
closeButton.buttonMode = true
|
|
closeButton.on('pointerdown', (e) => {
|
|
this.hide()
|
|
})
|
|
|
|
this._closeButton = closeButton
|
|
this.addChild(closeButton)
|
|
|
|
// maxWidth is set and a closeButton should be displayed
|
|
//-----------------
|
|
if (this.opts.maxWidth) {
|
|
const wordWrapWidth =
|
|
this.opts.maxWidth - 2 * this.opts.padding - this.smallPadding - this._closeButton.width
|
|
if (this._header) {
|
|
this.headerStyle.wordWrapWidth = wordWrapWidth
|
|
} else if (this._content) {
|
|
this.textStyle.wordWrapWidth = wordWrapWidth
|
|
}
|
|
}
|
|
}
|
|
|
|
// buttons
|
|
//-----------------
|
|
if (this.opts.button || this.opts.buttonGroup) {
|
|
if (this.opts.button) {
|
|
this._buttons = new Button(Object.assign({ textStyle: this.theme.textStyleSmall }, this.opts.button))
|
|
} else {
|
|
this._buttons = new ButtonGroup(
|
|
Object.assign({ textStyle: this.theme.textStyleSmall }, this.opts.buttonGroup)
|
|
)
|
|
}
|
|
this.addChild(this._buttons)
|
|
|
|
this._buttons.y = this.innerPadding + this.sy
|
|
}
|
|
|
|
return this
|
|
}
|
|
|
|
/**
|
|
* Should be called to refresh the layout of the popup. Can be used after resizing.
|
|
*
|
|
* @return {AbstractPopup} A reference to the popup for chaining.
|
|
*/
|
|
layout() {
|
|
super.layout()
|
|
|
|
// closeButton
|
|
//-----------------
|
|
if (this.opts.closeButton) {
|
|
this._closeButton.x = this.wantedWidth - this.smallPadding - this._closeButton.width
|
|
this._closeButton.y = this.smallPadding
|
|
}
|
|
|
|
// buttons
|
|
//-----------------
|
|
if (this._buttons) {
|
|
this._buttons.x = this.wantedWidth - this.opts.padding - this._buttons.width
|
|
this._buttons.y = this.wantedHeight - this.opts.padding - this._buttons.height
|
|
}
|
|
|
|
return this
|
|
}
|
|
|
|
/**
|
|
* Calculates the size of the children of the AbstractPopup.
|
|
* Cannot use getBounds() because it is not updated when children
|
|
* are removed.
|
|
*
|
|
* @private
|
|
* @override
|
|
* @returns {object} An JavaScript object width the keys width and height.
|
|
*/
|
|
getInnerSize() {
|
|
let size = super.getInnerSize()
|
|
|
|
if (this._closeButton) {
|
|
size.width += this.smallPadding + this._closeButton.width
|
|
}
|
|
|
|
if (this._buttons) {
|
|
size.width = Math.max(size.width, this._buttons.x + this._buttons.width)
|
|
size.height += this.innerPadding + this._buttons.height
|
|
}
|
|
|
|
return size
|
|
}
|
|
|
|
/**
|
|
* Tests if an icon string is an url.
|
|
*
|
|
* @private
|
|
* @static
|
|
* @param {string} url - The url to test.
|
|
* @return {boolean} true if the url is an url to an image.
|
|
*/
|
|
static iconIsUrl(url) {
|
|
return /\.(png|svg|gif|jpg|jpeg|tif|tiff)$/i.test(url)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Class that represents a PixiJS Popup.
|
|
*
|
|
* @example
|
|
* // Create the popup
|
|
* const popup = new Popup({
|
|
* header: 'Goethe',
|
|
* content: 'Man kann die Erfahrung nicht früh genug machen, wie entbehrlich man in der Welt ist.'
|
|
* })
|
|
*
|
|
* // Add the popup to a DisplayObject
|
|
* app.scene.addChild(popup)
|
|
*
|
|
* @class
|
|
* @extends InteractivePopup
|
|
* @see {@link https://www.iwm-tuebingen.de/iwmbrowser/lib/pixi/popup.html|DocTest}
|
|
*/
|
|
export default class Popup extends InteractivePopup {
|
|
/**
|
|
* Creates an instance of a Popup.
|
|
*
|
|
* @constructor
|
|
* @param {object} [opts] - An options object to specify to style and behaviour of the popup.
|
|
* @param {boolean|string} [opts.closeButton=false] - Should a close button be displayed on the upper right corner? Alternatively, a URL to the image can be specified.
|
|
* @param {number} [opts.minWidth=0] - The minimum width of the popup.
|
|
* @param {number} [opts.minHeight=0] - The minimum height of the popup.
|
|
*/
|
|
constructor(opts = {}) {
|
|
opts = Object.assign(
|
|
{},
|
|
{
|
|
closeButton: false,
|
|
minWidth: 0,
|
|
minHeight: 0,
|
|
},
|
|
opts
|
|
)
|
|
|
|
super(opts)
|
|
}
|
|
}
|