mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-31 11:09:04 +01:00
implement et2-searchbox and using it in NM
reorganized preprocessor a bit to fix some not replaced size attributes also pass on constructor args in all Et2Url widgets There is still a JS error in new searchbox, causing admin searchbox to not render :(
This commit is contained in:
parent
3cb8b1ecce
commit
ac0867ab77
@ -13,11 +13,12 @@
|
|||||||
use EGroupware\Api;
|
use EGroupware\Api;
|
||||||
|
|
||||||
// add et2- prefix to following widgets/tags, if NO <overlay legacy="true"
|
// add et2- prefix to following widgets/tags, if NO <overlay legacy="true"
|
||||||
const ADD_ET2_PREFIX_REGEXP = '#<((/?)([vh]?box|date(-time[^\s]*|-duration|-since)?|textbox|textarea|button|colorpicker|url(-email|-phone|-fax)?))(/?|\s[^>]*)>#m';
|
const ADD_ET2_PREFIX_REGEXP = '#<((/?)([vh]?box|date(-time[^\s]*|-duration|-since)?|button|colorpicker|url(-email|-phone|-fax)?))(/?|\s[^>]*)>#m';
|
||||||
const ADD_ET2_PREFIX_LAST_GROUP = 6;
|
const ADD_ET2_PREFIX_LAST_GROUP = 6;
|
||||||
|
|
||||||
// unconditional of legacy add et2- prefix to this widgets
|
// unconditional of legacy add et2- prefix to this widgets
|
||||||
const ADD_ET2_PREFIX_LEGACY_REGEXP = '#<(description|label|avatar|lavatar|image|vfs-mime|vfs-uid|vfs-gid|link|link-[a-z]+|favorites)\s([^>]+)/>#m';
|
const ADD_ET2_PREFIX_LEGACY_REGEXP = '#<(description|searchbox|label|avatar|lavatar|image|vfs-mime|vfs-uid|vfs-gid|link|link-[a-z]+|favorites)\s([^>]+)/>#m';
|
||||||
|
const ADD_ET2_PREFIX_LEGACY_LAST_GROUP = 2;
|
||||||
|
|
||||||
// switch evtl. set output-compression off, as we can't calculate a Content-Length header with transparent compression
|
// switch evtl. set output-compression off, as we can't calculate a Content-Length header with transparent compression
|
||||||
ini_set('zlib.output_compression', 0);
|
ini_set('zlib.output_compression', 0);
|
||||||
@ -160,8 +161,26 @@ function send_template()
|
|||||||
$str = preg_replace('/<(image|description)\s([^><]*)expose_view="true"\s([^><]*)\\/>/',
|
$str = preg_replace('/<(image|description)\s([^><]*)expose_view="true"\s([^><]*)\\/>/',
|
||||||
'<et2-$1-expose $2 $3></et2-$1-expose>', $str);
|
'<et2-$1-expose $2 $3></et2-$1-expose>', $str);
|
||||||
|
|
||||||
|
// fix <textbox multiline="true" .../> --> <et2-textarea .../>
|
||||||
|
$str = preg_replace('#<textbox(.*?)\smultiline="true"(.*?)/>#', '<et2-textarea$1$2></et2-textarea>', $str);
|
||||||
|
|
||||||
|
// fix <(textbox|int(eger)?|float) precision="int(eger)?|float" .../> --> <et2-number precision=.../> or <et2-textbox .../>
|
||||||
|
$str = preg_replace_callback('#<(textbox|int(eger)?|float|number).*?\s(type="(int(eger)?|float)")?.*?(/|></textbox)>#',
|
||||||
|
static function ($matches)
|
||||||
|
{
|
||||||
|
if ($matches[1] === 'textbox' && !in_array($matches[4], ['float', 'int', 'integer'], true))
|
||||||
|
{
|
||||||
|
return '<et2-'.substr($matches[0], 1, -strlen($matches[6])-1).'></et2-textbox>'; // regular textbox --> nothing to do
|
||||||
|
}
|
||||||
|
$type = $matches[1] === 'float' || $matches[4] === 'float' ? 'float' : 'int';
|
||||||
|
$tag = str_replace('<' . $matches[1], '<et2-number', substr($matches[0], 0, -2));
|
||||||
|
if (!empty($matches[3])) $tag = str_replace($matches[3], '', $tag);
|
||||||
|
if ($type !== 'float') $tag .= ' precision="0"';
|
||||||
|
return $tag . '></et2-number>';
|
||||||
|
}, $str);
|
||||||
|
|
||||||
// modify <(vfs-mime|link-string|link-list) --> <et2-*
|
// modify <(vfs-mime|link-string|link-list) --> <et2-*
|
||||||
$str = preg_replace(ADD_ET2_PREFIX_LEGACY_REGEXP, '<et2-$1 $2></et2-$1>',
|
$str = preg_replace(ADD_ET2_PREFIX_LEGACY_REGEXP, '<et2-$1 $'.ADD_ET2_PREFIX_LEGACY_LAST_GROUP.'></et2-$1>',
|
||||||
str_replace('<description/>', '<et2-description></et2-description>', $str));
|
str_replace('<description/>', '<et2-description></et2-description>', $str));
|
||||||
|
|
||||||
// change link attribute only_app to et2-link attribute app and map r/o link-entry to link
|
// change link attribute only_app to et2-link attribute app and map r/o link-entry to link
|
||||||
@ -278,33 +297,6 @@ function send_template()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// fix deprecated attributes: needed, blur, ...
|
|
||||||
static $deprecated = [
|
|
||||||
'needed' => 'required',
|
|
||||||
'blur' => 'placeholder',
|
|
||||||
];
|
|
||||||
$str = preg_replace_callback('#<[^ ]+[^>]* (' . implode('|', array_keys($deprecated)) . ')="([^"]+)"[ />]#',
|
|
||||||
static function ($matches) use ($deprecated) {
|
|
||||||
return str_replace($matches[1] . '="', $deprecated[$matches[1]] . '="', $matches[0]);
|
|
||||||
}, $str);
|
|
||||||
|
|
||||||
// fix <textbox multiline="true" .../> --> <textarea .../> (et2-prefix and self-closing is handled below)
|
|
||||||
$str = preg_replace('#<textbox(.*?)\smultiline="true"(.*?)/>#u', '<textarea$1$2/>', $str);
|
|
||||||
|
|
||||||
// fix <(textbox|int(eger)?|float) precision="int(eger)?|float" .../> --> <et2-number precision=...></et2-number>
|
|
||||||
$str = preg_replace_callback('#<(textbox|int(eger)?|float|number).*?\s(type="(int(eger)?|float)")?.*?/>#u',
|
|
||||||
static function ($matches) {
|
|
||||||
if ($matches[1] === 'textbox' && !in_array($matches[4], ['float', 'int', 'integer'], true))
|
|
||||||
{
|
|
||||||
return $matches[0]; // regular textbox --> nothing to do
|
|
||||||
}
|
|
||||||
$type = $matches[1] === 'float' || $matches[4] === 'float' ? 'float' : 'int';
|
|
||||||
$tag = str_replace('<' . $matches[1], '<et2-number', substr($matches[0], 0, -2));
|
|
||||||
if (!empty($matches[3])) $tag = str_replace($matches[3], '', $tag);
|
|
||||||
if ($type !== 'float') $tag .= ' precision="0"';
|
|
||||||
return $tag . '></et2-number>';
|
|
||||||
}, $str);
|
|
||||||
|
|
||||||
// fix <button(only)?.../> --> <et2-button(-image)? noSubmit="true".../>
|
// fix <button(only)?.../> --> <et2-button(-image)? noSubmit="true".../>
|
||||||
$str = preg_replace_callback('#<button(only)?\s(.*?)/>#u', function ($matches) use ($name) {
|
$str = preg_replace_callback('#<button(only)?\s(.*?)/>#u', function ($matches) use ($name) {
|
||||||
$tag = 'et2-button';
|
$tag = 'et2-button';
|
||||||
@ -354,8 +346,18 @@ function send_template()
|
|||||||
preg_match_all('/(^| )([a-z\d_-]+)="([^"]+)"/i', $matches[3], $attrs, PREG_PATTERN_ORDER);
|
preg_match_all('/(^| )([a-z\d_-]+)="([^"]+)"/i', $matches[3], $attrs, PREG_PATTERN_ORDER);
|
||||||
$attrs = array_combine($attrs[2], $attrs[3]);
|
$attrs = array_combine($attrs[2], $attrs[3]);
|
||||||
|
|
||||||
|
// fix deprecated attributes: needed, blur, ...
|
||||||
|
static $deprecated = [
|
||||||
|
'needed' => 'required',
|
||||||
|
'blur' => 'placeholder',
|
||||||
|
];
|
||||||
foreach($attrs as $name => $value)
|
foreach($attrs as $name => $value)
|
||||||
{
|
{
|
||||||
|
if (isset($deprecated[$name]))
|
||||||
|
{
|
||||||
|
unset($attrs[$name]);
|
||||||
|
$attrs[$name = $deprecated[$name]] = $value;
|
||||||
|
}
|
||||||
if (count($parts = preg_split('/[_-]/', $name)) > 1)
|
if (count($parts = preg_split('/[_-]/', $name)) > 1)
|
||||||
{
|
{
|
||||||
if ($name === 'parent_node') $parts[1] = 'Id'; // we can not use DOM property parentNode --> parentId
|
if ($name === 'parent_node') $parts[1] = 'Id'; // we can not use DOM property parentNode --> parentId
|
||||||
|
@ -38,9 +38,9 @@ export class Et2Password extends Et2InvokerMixin(Et2Textbox)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor()
|
constructor(...args : any[])
|
||||||
{
|
{
|
||||||
super();
|
super(...args);
|
||||||
|
|
||||||
this.plaintext = true;
|
this.plaintext = true;
|
||||||
this.suggest = 0;
|
this.suggest = 0;
|
||||||
|
81
api/js/etemplate/Et2Textbox/Et2Searchbox.ts
Normal file
81
api/js/etemplate/Et2Textbox/Et2Searchbox.ts
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/**
|
||||||
|
* EGroupware eTemplate2 - Searchbox widget
|
||||||
|
*
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
* @package api
|
||||||
|
* @link https://www.egroupware.org
|
||||||
|
* @author Ralf Becker
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable import/no-extraneous-dependencies */
|
||||||
|
import {Et2Textbox} from "./Et2Textbox";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @customElement et2-searchbox
|
||||||
|
*/
|
||||||
|
export class Et2Searchbox extends Et2Textbox
|
||||||
|
{
|
||||||
|
/** @type {any} */
|
||||||
|
static get properties()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
...super.properties,
|
||||||
|
/**
|
||||||
|
* Define whether the searchbox overlays while it's open (true) or stay as solid box in front of the search button (false). Default is false.
|
||||||
|
* @todo implement again
|
||||||
|
*/
|
||||||
|
overlay: Boolean,
|
||||||
|
/**
|
||||||
|
* Define whether the searchbox should be a fix input field or flexible search button. Default is true (fix).
|
||||||
|
* @todo implement again
|
||||||
|
*/
|
||||||
|
fix: Boolean,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(...args : any[])
|
||||||
|
{
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
this.overlay = false;
|
||||||
|
this.fix = true;
|
||||||
|
|
||||||
|
this.clearable = true;
|
||||||
|
this.type = 'search';
|
||||||
|
this.enterkeyhint = 'search';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overwritten to trigger a change/search
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
handleKeyDown(event: KeyboardEvent)
|
||||||
|
{
|
||||||
|
const hasModifier = event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;
|
||||||
|
|
||||||
|
// Pressing enter when focused on an input should submit the form like a native input, but we wait a tick before
|
||||||
|
// submitting to allow users to cancel the keydown event if they need to
|
||||||
|
if (event.key === 'Enter' && !hasModifier)
|
||||||
|
{
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
this._oldChange(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overwritten to trigger a change/search
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
handleClearClick(event : MouseEvent)
|
||||||
|
{
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
this.value = '';
|
||||||
|
this._oldChange(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// @ts-ignore TypeScript is not recognizing that this is a LitElement
|
||||||
|
customElements.define("et2-searchbox", Et2Searchbox);
|
@ -56,9 +56,10 @@ export class Et2Url extends Et2InvokerMixin(Et2Textbox)
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor()
|
constructor(...args : any[])
|
||||||
{
|
{
|
||||||
super();
|
super(...args);
|
||||||
|
|
||||||
this._invokerLabel = '⎆';
|
this._invokerLabel = '⎆';
|
||||||
this._invokerTitle = 'Open';
|
this._invokerTitle = 'Open';
|
||||||
this._invokerAction = () => {
|
this._invokerAction = () => {
|
||||||
|
@ -34,9 +34,10 @@ export class Et2UrlEmail extends Et2InvokerMixin(Et2Textbox)
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor()
|
constructor(...args : any[])
|
||||||
{
|
{
|
||||||
super();
|
super(...args);
|
||||||
|
|
||||||
this.defaultValidators.push(new IsEmail());
|
this.defaultValidators.push(new IsEmail());
|
||||||
this._invokerLabel = '@';
|
this._invokerLabel = '@';
|
||||||
this._invokerTitle = 'Compose mail to';
|
this._invokerTitle = 'Compose mail to';
|
||||||
|
@ -73,11 +73,6 @@ export class Et2UrlEmailReadonly extends Et2UrlReadonly
|
|||||||
return super.value;
|
return super.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor()
|
|
||||||
{
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
transformAttributes(attrs)
|
transformAttributes(attrs)
|
||||||
{
|
{
|
||||||
if (typeof attrs.onclick === 'undefined')
|
if (typeof attrs.onclick === 'undefined')
|
||||||
|
@ -34,9 +34,10 @@ export class Et2UrlFax extends Et2UrlPhone
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor()
|
constructor(...args : any[])
|
||||||
{
|
{
|
||||||
super();
|
super(...args);
|
||||||
|
|
||||||
//this.defaultValidators.push(...);
|
//this.defaultValidators.push(...);
|
||||||
this._invokerLabel = '📠';
|
this._invokerLabel = '📠';
|
||||||
this._invokerTitle = 'Send';
|
this._invokerTitle = 'Send';
|
||||||
|
@ -16,11 +16,6 @@ import {Et2UrlReadonly} from "./Et2UrlReadonly";
|
|||||||
*/
|
*/
|
||||||
export class Et2UrlFaxReadonly extends Et2UrlReadonly
|
export class Et2UrlFaxReadonly extends Et2UrlReadonly
|
||||||
{
|
{
|
||||||
constructor()
|
|
||||||
{
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
transformAttributes(attrs)
|
transformAttributes(attrs)
|
||||||
{
|
{
|
||||||
if (typeof attrs.onclick === 'undefined')
|
if (typeof attrs.onclick === 'undefined')
|
||||||
|
@ -32,9 +32,10 @@ export class Et2UrlPhone extends Et2InvokerMixin(Et2Textbox)
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor()
|
constructor(...args : any[])
|
||||||
{
|
{
|
||||||
super();
|
super(...args);
|
||||||
|
|
||||||
//this.defaultValidators.push(...);
|
//this.defaultValidators.push(...);
|
||||||
this._invokerLabel = '✆';
|
this._invokerLabel = '✆';
|
||||||
this._invokerTitle = 'Call';
|
this._invokerTitle = 'Call';
|
||||||
|
@ -16,11 +16,6 @@ import {Et2UrlReadonly} from "./Et2UrlReadonly";
|
|||||||
*/
|
*/
|
||||||
export class Et2UrlPhoneReadonly extends Et2UrlReadonly
|
export class Et2UrlPhoneReadonly extends Et2UrlReadonly
|
||||||
{
|
{
|
||||||
constructor()
|
|
||||||
{
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
transformAttributes(attrs)
|
transformAttributes(attrs)
|
||||||
{
|
{
|
||||||
if (typeof attrs.onclick === 'undefined')
|
if (typeof attrs.onclick === 'undefined')
|
||||||
|
@ -19,11 +19,6 @@ import {Et2Url} from "./Et2Url";
|
|||||||
*/
|
*/
|
||||||
export class Et2UrlReadonly extends Et2Description
|
export class Et2UrlReadonly extends Et2Description
|
||||||
{
|
{
|
||||||
constructor()
|
|
||||||
{
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles()
|
static get styles()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
@ -77,6 +77,7 @@ import {loadWebComponent} from "./Et2Widget/Et2Widget";
|
|||||||
import {Et2AccountFilterHeader} from "./Nextmatch/Headers/AccountFilterHeader";
|
import {Et2AccountFilterHeader} from "./Nextmatch/Headers/AccountFilterHeader";
|
||||||
import {Et2SelectCategory} from "./Et2Select/Et2SelectCategory";
|
import {Et2SelectCategory} from "./Et2Select/Et2SelectCategory";
|
||||||
import {Et2ColumnSelection} from "./Et2Nextmatch/ColumnSelection";
|
import {Et2ColumnSelection} from "./Et2Nextmatch/ColumnSelection";
|
||||||
|
import {Et2Searchbox} from "./Et2Textbox/Et2Searchbox";
|
||||||
|
|
||||||
//import {et2_selectAccount} from "./et2_widget_SelectAccount";
|
//import {et2_selectAccount} from "./et2_widget_SelectAccount";
|
||||||
let keep_import : Et2AccountFilterHeader
|
let keep_import : Et2AccountFilterHeader
|
||||||
@ -3208,7 +3209,7 @@ export class et2_nextmatch_header_bar extends et2_DOMWidget implements et2_INext
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
headers : { id : string }[] | et2_widget[];
|
headers : { id : string }[] | et2_widget[];
|
||||||
et2_searchbox : et2_inputWidget;
|
et2_searchbox : Et2Searchbox;
|
||||||
private favorites : et2_DOMWidget; // Actually favorite
|
private favorites : et2_DOMWidget; // Actually favorite
|
||||||
|
|
||||||
private nextmatch : et2_nextmatch;
|
private nextmatch : et2_nextmatch;
|
||||||
@ -3324,14 +3325,14 @@ export class et2_nextmatch_header_bar extends et2_DOMWidget implements et2_INext
|
|||||||
{
|
{
|
||||||
self.nextmatch.applyFilters({search: this.get_value()});
|
self.nextmatch.applyFilters({search: this.get_value()});
|
||||||
},
|
},
|
||||||
value: settings.search,
|
value: settings.search || '',
|
||||||
fix: !egwIsMobile()
|
fix: !egwIsMobile()
|
||||||
};
|
};
|
||||||
// searchbox widget
|
// searchbox widget
|
||||||
this.et2_searchbox = <et2_searchbox>et2_createWidget('searchbox', searchbox_options, this);
|
this.et2_searchbox = <Et2Searchbox>loadWebComponent('et2-searchbox', searchbox_options, this);
|
||||||
|
|
||||||
// Set activeFilters to current value
|
// Set activeFilters to current value
|
||||||
this.nextmatch.activeFilters.search = settings.search;
|
this.nextmatch.activeFilters.search = settings.search || '';
|
||||||
|
|
||||||
this.et2_searchbox.set_value(settings.search);
|
this.et2_searchbox.set_value(settings.search);
|
||||||
jQuery(this.et2_searchbox.getInputNode()).attr("aria-label", egw.lang("search"));
|
jQuery(this.et2_searchbox.getInputNode()).attr("aria-label", egw.lang("search"));
|
||||||
|
@ -86,6 +86,7 @@ import "./Layout/RowLimitedMixin";
|
|||||||
import "./Et2Vfs/Et2VfsMime";
|
import "./Et2Vfs/Et2VfsMime";
|
||||||
import "./Et2Vfs/Et2VfsUid";
|
import "./Et2Vfs/Et2VfsUid";
|
||||||
import "./Et2Textbox/Et2Password";
|
import "./Et2Textbox/Et2Password";
|
||||||
|
import './Et2Textbox/Et2Searchbox';
|
||||||
|
|
||||||
/* Include all widget classes here, we only care about them registering, not importing anything*/
|
/* Include all widget classes here, we only care about them registering, not importing anything*/
|
||||||
import './et2_widget_vfs'; // Vfs must be first (before et2_widget_file) due to import cycle
|
import './et2_widget_vfs'; // Vfs must be first (before et2_widget_file) due to import cycle
|
||||||
|
Loading…
Reference in New Issue
Block a user