2021-06-23 23:39:58 +02:00
|
|
|
/**
|
|
|
|
* EGroupware eTemplate2 - Button widget
|
|
|
|
*
|
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
|
|
* @package etemplate
|
|
|
|
* @subpackage api
|
|
|
|
* @link https://www.egroupware.org
|
|
|
|
* @author Nathan Gray
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2021-08-26 22:18:31 +02:00
|
|
|
import {css, html} from "@lion/core";
|
2021-08-27 08:13:36 +02:00
|
|
|
import {LionButton} from "@lion/button";
|
|
|
|
import {SlotMixin} from "@lion/core";
|
2021-08-25 19:32:15 +02:00
|
|
|
import {Et2InputWidget} from "../Et2InputWidget/Et2InputWidget";
|
2022-01-18 15:13:48 +01:00
|
|
|
import {buttonStyles} from "./ButtonStyles";
|
2021-07-14 17:49:36 +02:00
|
|
|
|
2021-08-26 20:59:13 +02:00
|
|
|
export class Et2Button extends Et2InputWidget(SlotMixin(LionButton))
|
2021-06-23 23:39:58 +02:00
|
|
|
{
|
2021-08-19 01:41:23 +02:00
|
|
|
protected _created_icon_node : HTMLImageElement;
|
|
|
|
protected clicked : boolean = false;
|
2021-08-25 23:24:27 +02:00
|
|
|
private _image : string;
|
2021-08-13 23:26:18 +02:00
|
|
|
|
2021-09-15 19:08:44 +02:00
|
|
|
/**
|
|
|
|
* images to be used as background-image, if none is explicitly applied and id matches given regular expression
|
|
|
|
*/
|
|
|
|
static readonly default_background_images : object = {
|
|
|
|
save: /save(&|\]|$)/,
|
|
|
|
apply: /apply(&|\]|$)/,
|
|
|
|
cancel: /cancel(&|\]|$)/,
|
|
|
|
delete: /delete(&|\]|$)/,
|
|
|
|
discard: /discard(&|\]|$)/,
|
|
|
|
edit: /edit(&|\[\]|$)/,
|
|
|
|
next: /(next|continue)(&|\]|$)/,
|
|
|
|
finish: /finish(&|\]|$)/,
|
|
|
|
back: /(back|previous)(&|\]|$)/,
|
|
|
|
copy: /copy(&|\]|$)/,
|
|
|
|
more: /more(&|\]|$)/,
|
|
|
|
check: /(yes|check)(&|\]|$)/,
|
|
|
|
cancelled: /no(&|\]|$)/,
|
|
|
|
ok: /ok(&|\]|$)/,
|
|
|
|
close: /close(&|\]|$)/,
|
|
|
|
add: /(add(&|\]|$)|create)/ // customfields use create*
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Classnames added automatically to buttons to set certain hover background colors
|
|
|
|
*/
|
|
|
|
static readonly default_classes : object = {
|
|
|
|
et2_button_cancel: /cancel(&|\]|$)/, // yellow
|
|
|
|
et2_button_question: /(yes|no)(&|\]|$)/, // yellow
|
|
|
|
et2_button_delete: /delete(&|\]|$)/ // red
|
|
|
|
};
|
|
|
|
|
2021-08-13 23:26:18 +02:00
|
|
|
static get styles()
|
|
|
|
{
|
|
|
|
return [
|
|
|
|
...super.styles,
|
2022-01-18 15:13:48 +01:00
|
|
|
buttonStyles,
|
2021-08-13 23:26:18 +02:00
|
|
|
css`
|
2021-07-19 19:57:06 +02:00
|
|
|
:host {
|
2022-01-19 18:30:45 +01:00
|
|
|
padding: 0;
|
2021-07-19 19:57:06 +02:00
|
|
|
/* These should probably come from somewhere else */
|
2022-01-18 15:13:48 +01:00
|
|
|
max-width: 125px;
|
2021-07-19 19:57:06 +02:00
|
|
|
}
|
2021-08-19 18:54:32 +02:00
|
|
|
:host([readonly]) {
|
|
|
|
display: none;
|
|
|
|
}
|
2021-07-19 19:57:06 +02:00
|
|
|
/* Set size for icon */
|
2021-09-14 19:43:43 +02:00
|
|
|
::slotted([slot="icon"][src]) {
|
2021-07-19 19:57:06 +02:00
|
|
|
width: 20px;
|
|
|
|
padding-right: 3px;
|
2021-09-14 19:43:43 +02:00
|
|
|
}
|
|
|
|
::slotted([slot="icon"][src='']) {
|
|
|
|
display: none;
|
|
|
|
}
|
2022-01-19 18:30:45 +01:00
|
|
|
.imageOnly {
|
|
|
|
width:20px;
|
|
|
|
height: 20px;
|
|
|
|
background-color: var(--bg_color_5_gray);
|
|
|
|
}
|
2021-09-14 19:43:43 +02:00
|
|
|
`,
|
2021-08-13 23:26:18 +02:00
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
static get properties()
|
|
|
|
{
|
|
|
|
return {
|
|
|
|
...super.properties,
|
2021-08-19 01:41:23 +02:00
|
|
|
image: {type: String}
|
2021-08-10 23:02:52 +02:00
|
|
|
}
|
2021-08-13 23:26:18 +02:00
|
|
|
}
|
2021-08-10 23:02:52 +02:00
|
|
|
|
2021-08-23 19:49:17 +02:00
|
|
|
|
2021-08-13 23:26:18 +02:00
|
|
|
constructor()
|
|
|
|
{
|
|
|
|
super();
|
2021-08-10 23:02:52 +02:00
|
|
|
|
2021-08-13 23:26:18 +02:00
|
|
|
// Property default values
|
2021-08-25 23:24:27 +02:00
|
|
|
this._image = '';
|
2021-08-10 23:02:52 +02:00
|
|
|
|
2021-08-23 19:49:17 +02:00
|
|
|
// Do not add icon here, no children can be added in constructor
|
2021-08-13 23:26:18 +02:00
|
|
|
|
|
|
|
}
|
2021-08-10 23:02:52 +02:00
|
|
|
|
2021-08-13 23:26:18 +02:00
|
|
|
connectedCallback()
|
|
|
|
{
|
|
|
|
super.connectedCallback();
|
2021-08-10 23:02:52 +02:00
|
|
|
|
2021-08-13 23:26:18 +02:00
|
|
|
//this.classList.add("et2_button")
|
2021-08-25 23:24:27 +02:00
|
|
|
}
|
2021-08-10 23:02:52 +02:00
|
|
|
|
2021-08-25 23:24:27 +02:00
|
|
|
set image(new_image : string)
|
|
|
|
{
|
|
|
|
let oldValue = this._image;
|
|
|
|
if(new_image.indexOf("http") >= 0)
|
|
|
|
{
|
|
|
|
this._image = new_image
|
|
|
|
}
|
|
|
|
else
|
2021-08-13 23:26:18 +02:00
|
|
|
{
|
2021-08-25 23:24:27 +02:00
|
|
|
this._image = this.egw().image(new_image, 'etemplate');
|
2021-08-10 23:02:52 +02:00
|
|
|
}
|
2021-08-25 23:24:27 +02:00
|
|
|
this.requestUpdate("image", oldValue);
|
2021-08-13 23:26:18 +02:00
|
|
|
}
|
2021-08-10 23:02:52 +02:00
|
|
|
|
2021-08-19 01:41:23 +02:00
|
|
|
_handleClick(event : MouseEvent) : boolean
|
2021-08-13 23:26:18 +02:00
|
|
|
{
|
|
|
|
// ignore click on readonly button
|
2021-08-25 19:32:15 +02:00
|
|
|
if(this.disabled || this.readonly)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2021-08-10 23:02:52 +02:00
|
|
|
|
2021-08-13 23:26:18 +02:00
|
|
|
this.clicked = true;
|
2021-08-10 23:02:52 +02:00
|
|
|
|
2021-08-13 23:26:18 +02:00
|
|
|
// Cancel buttons don't trigger the close confirmation prompt
|
2021-08-19 01:41:23 +02:00
|
|
|
if(this.classList.contains("et2_button_cancel"))
|
2021-08-10 23:02:52 +02:00
|
|
|
{
|
2021-08-13 23:26:18 +02:00
|
|
|
this.getInstanceManager()?.skip_close_prompt();
|
2021-08-10 23:02:52 +02:00
|
|
|
}
|
|
|
|
|
2021-08-19 01:41:23 +02:00
|
|
|
if(!super._handleClick(event))
|
2021-08-10 23:02:52 +02:00
|
|
|
{
|
2021-08-13 23:26:18 +02:00
|
|
|
this.clicked = false;
|
|
|
|
return false;
|
2021-08-10 23:02:52 +02:00
|
|
|
}
|
|
|
|
|
2021-09-15 19:08:44 +02:00
|
|
|
// Submit the form
|
|
|
|
if(this.getType() !== "buttononly")
|
|
|
|
{
|
|
|
|
return this.getInstanceManager().submit();
|
|
|
|
}
|
2021-08-13 23:26:18 +02:00
|
|
|
this.clicked = false;
|
|
|
|
this.getInstanceManager()?.skip_close_prompt(false);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-09-15 19:08:44 +02:00
|
|
|
/**
|
|
|
|
* Handle changes that have to happen based on changes to properties
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
requestUpdate(name : PropertyKey, oldValue)
|
|
|
|
{
|
|
|
|
super.requestUpdate(name, oldValue);
|
|
|
|
|
|
|
|
// Default image & class are determined based on ID
|
|
|
|
if(name == "id" && this._widget_id)
|
|
|
|
{
|
|
|
|
// Check against current value to avoid triggering another update
|
|
|
|
if(!this.image)
|
|
|
|
{
|
|
|
|
let image = this._get_default_image(this._widget_id);
|
|
|
|
if(image != this._image)
|
|
|
|
{
|
2021-09-16 21:35:41 +02:00
|
|
|
this.image = image;
|
2021-09-15 19:08:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
let default_class = this._get_default_class(this._widget_id);
|
|
|
|
if(default_class && !this.classList.contains(default_class))
|
|
|
|
{
|
2021-09-16 21:35:41 +02:00
|
|
|
this.classList.add(default_class);
|
2021-09-15 19:08:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-13 23:26:18 +02:00
|
|
|
render()
|
|
|
|
{
|
2021-08-23 19:49:17 +02:00
|
|
|
if(this.readonly)
|
|
|
|
{
|
|
|
|
return '';
|
|
|
|
}
|
2021-08-13 23:26:18 +02:00
|
|
|
return html`
|
2022-01-19 18:30:45 +01:00
|
|
|
<div class="button-content et2_button ${this._label?'':'imageOnly'}" id="${this._buttonId}" style="background-image: url(${this._image})">
|
|
|
|
<slot name="label">${this._label}</slot>
|
2021-08-13 23:26:18 +02:00
|
|
|
</div> `;
|
|
|
|
}
|
|
|
|
|
2021-09-15 19:08:44 +02:00
|
|
|
/**
|
|
|
|
* Get a default image for the button based on ID
|
|
|
|
*
|
|
|
|
* @param {string} check_id
|
|
|
|
*/
|
|
|
|
_get_default_image(check_id : string) : string
|
|
|
|
{
|
|
|
|
if(!check_id)
|
|
|
|
{
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
if(typeof this.image == 'undefined')
|
|
|
|
{
|
|
|
|
for(const image in Et2Button.default_background_images)
|
|
|
|
{
|
|
|
|
if(check_id.match(Et2Button.default_background_images[image]))
|
|
|
|
{
|
|
|
|
return image;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a default class for the button based on ID
|
|
|
|
*
|
|
|
|
* @param check_id
|
|
|
|
* @returns {string}
|
|
|
|
*/
|
|
|
|
_get_default_class(check_id)
|
|
|
|
{
|
|
|
|
if(!check_id)
|
|
|
|
{
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
for(var name in Et2Button.default_classes)
|
|
|
|
{
|
|
|
|
if(check_id.match(Et2Button.default_classes[name]))
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2021-08-23 19:49:17 +02:00
|
|
|
get _iconNode() : HTMLImageElement
|
|
|
|
{
|
|
|
|
return <HTMLImageElement>(Array.from(this.children)).find(
|
2021-08-26 20:59:13 +02:00
|
|
|
el => (<HTMLElement>el).slot === "icon",
|
2021-08-23 19:49:17 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-08-13 23:26:18 +02:00
|
|
|
/**
|
|
|
|
* Implementation of the et2_IInput interface
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Always return false as a button is never dirty
|
|
|
|
*/
|
|
|
|
isDirty()
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
resetDirty()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
getValue()
|
|
|
|
{
|
2021-08-19 01:41:23 +02:00
|
|
|
if(this.clicked)
|
2021-08-10 23:02:52 +02:00
|
|
|
{
|
2021-08-13 23:26:18 +02:00
|
|
|
return true;
|
2021-08-10 23:02:52 +02:00
|
|
|
}
|
2021-08-13 23:26:18 +02:00
|
|
|
|
|
|
|
// If "null" is returned, the result is not added to the submitted
|
|
|
|
// array.
|
|
|
|
return null;
|
|
|
|
}
|
2021-06-23 23:39:58 +02:00
|
|
|
}
|
2021-08-10 23:02:52 +02:00
|
|
|
|
2021-08-27 19:21:40 +02:00
|
|
|
// @ts-ignore TypeScript is not recognizing that Et2Button is a LitElement
|
2021-08-10 23:02:52 +02:00
|
|
|
customElements.define("et2-button", Et2Button);
|