Skip to content

Commit

Permalink
Item15298: multiple improvements
Browse files Browse the repository at this point in the history
- attachment+multi formfields now allow to upload multiple files at once
- new formfield uuid
- added mindate and maxdate to date2 and datetime formfields
- added new formfield type masked for masked text input
- added masked input to time and datetime fields
- added weekend parameter to date2 and datetime fields
- added upload parameter to attachment field
- added unit tests
  • Loading branch information
MichaelDaum committed Feb 1, 2024
1 parent 384a248 commit d1cd999
Show file tree
Hide file tree
Showing 79 changed files with 1,622 additions and 734 deletions.
74 changes: 70 additions & 4 deletions data/System/MoreFormfieldsPlugin.txt
@@ -1,4 +1,4 @@
%META:TOPICINFO{author="ProjectContributor" comment="reprev" date="1616150870" format="1.1" version="1"}%
%META:TOPICINFO{author="ProjectContributor" comment="reprev" date="1692614734" format="1.1" version="1"}%
---+!! %TOPIC%
%FORMFIELD{"Description"}%

Expand All @@ -20,6 +20,7 @@ To make use of these formfields use their type identifier in the "Type" column o
| Ipaddress | ipaddress | 15 | | | |
| Ipv6address | ipv6address | 40 | | | |
| Macaddress | macaddress | 17 | | | |
| Masked | masked | 17 | | | |
| Natedit | natedit | 80x25 | | | |
| Multitext | multitext | 80 | | | |
| Netmask | netmask | 15 | | | |
Expand All @@ -33,6 +34,7 @@ To make use of these formfields use their type identifier in the "Type" column o
| Topic | topic | 30 | | | |
| User Or Group | userorgroup | 30 | | | |
| User | user | 30 | | | |
| Uuid | uuid | 30 | | | |
| Web | web | 30 | | | |

When defining a formfield additional parameters may be used in the "Values" column to further customize the behavior of the element.
Expand All @@ -50,6 +52,7 @@ specified in the =topic= parameter. The formfield lets you upload new attachment
* =url=: url for autocompletion, defaults to an internal template =select2::attachment::url=
* =filter=: regular expression of files allowed to be uploaded
* =sortable=: entries in an =attachment+multi= formfield can be reordered using drag'n'drop if set to =true=
* =upload=: boolean switch to enable/disable uploading an attachment, defaults to =off=

---+++ autofill

Expand Down Expand Up @@ -78,6 +81,16 @@ A typical use-case for an =autofill= field is the construction of a !TopicTitle
| ID | id | 4 | | | |
| Year | text | 4 | | | |

An =autofill= formfield is either displayed as created by the formating rules. Or the resulting value may be displayed otherwise using
a =display="..."= wiki app. Another more comfortable way is to cast the value into a different formfield type using the =type="..."= parameter.
That way the computed value may be displayed using the formfield definition of the given type. The following example will query the date of the most
recent comment and store it as epoch seconds in a "Last Reply" formfield. It is then displayed using the =Datetime= definition instead of displaying
the epoch seconds as is:

| *Name* | *Type* | *Size* | *Values* | *Description* | *Attributes* |
| Last Reply | autofill | 1 | type="datetime" format="$percntFORMATLIST{\"$percntQUERY{\"'$percntBASEWEB$percnt.$percntBASETOPIC$percnt'/META:COMMENT.date\"}$percnt\" sort=\"on\" reverse=\"on\" limit=\"1\"}$percnt" | date of latest reply | | |


---+++ autoinc

This is a formfield type that extens Foswiki's core AUTOINC mechanism to enumerate topics when they are created and brings it to
Expand Down Expand Up @@ -124,6 +137,25 @@ It will launch a calendar when clicking into a =date2= formfield to select a dat
will always be of a =YYYY-MM-DD= pattern and thus not be depending on any locale settings. This is quite important to get consistant data rather than differences based on the user's current browser language.
While the _value_ stored into a =date2= formfield is locale-independent will it display according to the settings of =$Foswiki::cfg{DefaultDateFormat}= settings.

Example:

| Date | date2 | 40 | mindate="-7d" maxdate="+7d" weekends="off" | | |

---+++ datetime

This formfield type combines a =date2= formfield with a =time= formfield thus letting you pick a date time with a minute precision.

Example:

| *Name* | *Type* | *Size* | *Values* | *Description* | *Attributes* |
| Datetime | datetime | 10 | lang="en" timezone="gmtime" | | |

*Parameters*:

* =lang=: language of the input element, defaults to the current user's interface language
* =format=: display format of the field, default to =$Foswiki::cfg{DateManipPlugin}{DefaultDateTimeFormat}= or =%d %b %Y - %H:%M=
* =tz=, =timezone=: timezone defaults to the one definied in =LocalSite.cfg= that is gmtime or servertime

---+++ group

A group reference using !JQSelect2Contrib for autocompletion.
Expand Down Expand Up @@ -210,6 +242,15 @@ A hardware address given in 6 hex values, e.g. =00:1a:10:6f:ba:12=

*Parameters*: none

---+++ masked

A normal textfield with optional masked input using [[JQueryMaskedInput]]

*Parameters*:

* =mask=: input mask
* =placeholder=: placeholder character, defaults to underscore

---+++ multitext

This is a kind of =text+multi= formfield. it stores multiple text formfields in one.
Expand Down Expand Up @@ -248,7 +289,7 @@ A standard telephone number. This formfield uses [[JQueryValidate]] to make sure

---+++ random

This formfield type that generates a random value the first time the topic is created. There are a set of different random strings:
This formfield type generates a random value the first time the topic is created. There are a set of different random strings:

* alpha
* upperalpha
Expand Down Expand Up @@ -311,6 +352,11 @@ The "any value" selection is the one indicated by the "*" asterisk, or if not pr

A time formfield using the clockpicker widget from http://weareoutman.github.io/clockpicker/

Example:

| *Name* | *Type* | *Size* | *Values* | *Description* | *Attributes* |
| Time | time | 10 | | | |

---+++ toggle

A toggle formfield may switch between two values, by default between "on" and "off". Alternative values may be specified like this:
Expand Down Expand Up @@ -358,11 +404,24 @@ A user reference using !JQSelect2Contrib for autocompletion.
*Parameters*:

* =url=: url for autocompletion, default: =%<nop>SCRIPTURL{"rest"}%/MoreFormfieldsPlugin/users=
* =group=: groups that users must be a member of to be included in the selection
* =group=: members of one or more groups to select from
* =include=: regular expression a user must match to be included in the selection
* =exclude=: regular expression a user must not match to be included
* =sortable=: entries in an =user+multi= formfield can be reordered using drag'n'drop if set to =true=

---+++ uuid

This formfield type generates a random UUID code the first time the topic is created.

| *Name* | *Type* | *Size* | *Values* | *Description* | *Attributes* |
| Uuid | uuid | 30 | prefix="foobar" charset="upperalpha" | | |

The charset might be: =upperalpha= (default) or =loweralpha=

UUIDs have got the format =XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX= where the X chars are upper or lowercase hex values as specified by
the =charset= parameter.
An optional =prefix= parameter might be specified in which case the code will be =&lt;prefix>-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX=.

---+++ web

This formfield stores a reference to web.
Expand All @@ -383,6 +442,13 @@ This formfield stores a reference to web.

---++ Change History
%TABLE{columnwidths="7em" tablewidth="100%"}%
| 04 Dec 2023: | added =upload= parameter to =attachment= field |
| 30 Nov 2023: | added =weekend= parameter to =date2= and =datetime= fields |
| 11 Oct 2023: | added masked input to =time= and =datetime= fields; \
added new formfield type =masked= for masked text input |
| 29 Aug 2023: | added =mindate= and =maxdate= to =date2= and =datetime= formfields |
| 21 Jul 2023: | new formfield =uuid= |
| 21 Oct 2022: | attachment+multi formfields now allow to upload multiple files at once |
| 05 May 2022: | new major release |
| 17 Dec 2021: | added =from= parameter to =id= formfield |
| 02 Nov 2021: | new formfield =random= |
Expand Down Expand Up @@ -426,7 +492,7 @@ This formfield stores a reference to web.
%META:FIELD{name="Release" title="Release" value="%25$RELEASE%25"}%
%META:FIELD{name="Description" title="Description" value="%25$SHORTDESCRIPTION%25"}%
%META:FIELD{name="Repository" title="Repository" value="https://github.com/foswiki/%25TOPIC%25"}%
%META:FIELD{name="Copyright" title="Copyright" value="&copy; 2010-2022 Michael Daum"}%
%META:FIELD{name="Copyright" title="Copyright" value="&copy; 2010-2024 Michael Daum"}%
%META:FIELD{name="License" title="License" value="[[http://www.gnu.org/licenses/gpl.html][GPL (Gnu General Public License)]]"}%
%META:FIELD{name="Home" title="Home" value="Foswiki:Extensions/%25TOPIC%25"}%
%META:FIELD{name="Support" title="Support" value="Foswiki:Support/%25TOPIC%25"}%
67 changes: 17 additions & 50 deletions lib/Foswiki/Form/Attachment.pm
@@ -1,6 +1,6 @@
# Plugin for Foswiki - The Free and Open Source Wiki, http://foswiki.org/
#
# MoreFormfieldsPlugin is Copyright (C) 2010-2022 Michael Daum http://michaeldaumconsulting.com
# MoreFormfieldsPlugin is Copyright (C) 2010-2024 Michael Daum http://michaeldaumconsulting.com
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
Expand All @@ -18,9 +18,9 @@ use strict;
use warnings;

use Foswiki::Func();
use Foswiki::Form::FieldDefinition ();
use Foswiki::Form::BaseField ();
use Foswiki::Plugins::JQueryPlugin ();
our @ISA = ('Foswiki::Form::FieldDefinition');
our @ISA = ('Foswiki::Form::BaseField');

sub new {
my $class = shift;
Expand All @@ -36,26 +36,17 @@ sub new {
$this->{_web} = $this->param("web") || $this->{session}{webName};
$this->{_topic} = $this->param("topic") || $this->{session}{topicName};
$this->{_url} = Foswiki::Func::expandTemplate("select2::attachments::url");
$this->{_enableUpload} = Foswiki::Func::isTrue($this->param("upload"));
return $this;
}

sub isMultiValued { return (shift->{type} =~ m/\+multi/); }

sub isTextMergeable { return 0; }

sub getDefaultValue {
my $this = shift;

my $value = $this->{default};
$value = '' unless defined $value;

return $value;
}

sub finish {
my $this = shift;
$this->SUPER::finish();
undef $this->{_params};
undef $this->{_options};
}

Expand Down Expand Up @@ -109,17 +100,6 @@ sub getOptions {
return [];
}

sub param {
my ($this, $key) = @_;

unless (defined $this->{_params}) {
my %params = Foswiki::Func::extractParameters($this->{value});
$this->{_params} = \%params;
}

return (defined $key) ? $this->{_params}{$key} : $this->{_params};
}

sub getDisplayValue {
my ($this, $value, $web, $topic) = @_;

Expand Down Expand Up @@ -148,6 +128,8 @@ sub getDisplayValue {
push @result, $format;
}

$this->addStyles();

my $result = join("", @result);
return $result =~ /%/ ? Foswiki::Func::expandCommonVariables($result, $topic, $web) : $result;
}
Expand Down Expand Up @@ -177,16 +159,6 @@ sub _getHref {
return wantarray ? ($href, $cls) : $href;
}

sub renderForDisplay {
my ($this, $format, $value, $attrs) = @_;

my $displayValue = $this->getDisplayValue($value);
$format =~ s/\$value\(display\)/$displayValue/g;
$format =~ s/\$value/$value/g;

return $this->SUPER::renderForDisplay($format, $value, $attrs);
}

sub renderForEdit {
my ($this, $topicObject, $value) = @_;

Expand All @@ -203,10 +175,12 @@ sub renderForEdit {
push @htmlData, 'class="' . $this->cssClasses($this->{_formfieldClass}) . '"';
push @htmlData, 'name="' . $this->{name} . '"';
push @htmlData, 'value="' . $value . '"';
push @htmlData, 'data-multiple="true"' if $this->isMultiValued;

my @uploadButtonHtmlData = ();
push @uploadButtonHtmlData, "data-topic='$web.$topic'";
push @uploadButtonHtmlData, "data-auto-upload='false'";
push @uploadButtonHtmlData, "data-multi-file-upload='true'" if $this->isMultiValued;

my $size = $this->{size};
if (defined $size) {
Expand Down Expand Up @@ -237,37 +211,30 @@ sub renderForEdit {
}
}

if ($this->isMultiValued) {
push @htmlData, 'data-multiple="true"';
}

$this->addJavascript();
$this->addJavaScript();
$this->addStyles();

my $htmlData = join(" ", @htmlData);
my $result = "<input $htmlData />";

my $uploadButtonHtmlData = join(" ", @uploadButtonHtmlData);
my $name = "_" . $this->{name} . ($this->isMultiValued ? '[]' : '');
$result .= <<HERE;
my $input = "<input type='file' name='_$this->{name}' / >";
$input = "<input type='file' name='_".$this->{name}."[]' multiple / >" if $this->isMultiValued;

if ($this->{_enableUpload}) {
$result .= <<HERE;
<span class='jqButton jqButtonSimple jqUploadButton' $uploadButtonHtmlData>
<i class='jqButtonIcon fa-fw fa fa-upload'></i>
<input type='file' name='$name' / >
$input
</span>
HERE
}

return ('', $result);
}

sub addStyles {
#my $this = shift;
Foswiki::Func::addToZone("head",
"MOREFORMFIELDSPLUGIN::CSS",
"<link rel='stylesheet' href='%PUBURLPATH%/%SYSTEMWEB%/MoreFormfieldsPlugin/moreformfields.css' media='all' />",
"JQUERYPLUGIN::SELECT2");
}

sub addJavascript {
sub addJavaScript {
#my $this = shift;

Foswiki::Plugins::JQueryPlugin::createPlugin("fontawesome");
Expand Down

0 comments on commit d1cd999

Please sign in to comment.