Added hidden Select2 input widget
authorThierry Florac <thierry.florac@onf.fr>
Tue, 17 Jul 2018 18:02:48 +0200
changeset 131 16241f36971b
parent 130 d02e4a8ad35a
child 132 772f71ac0698
Added hidden Select2 input widget
src/pyams_form/widget/__init__.py
src/pyams_form/widget/templates/hidden-select-input.pt
--- a/src/pyams_form/widget/__init__.py	Fri Jul 13 12:22:22 2018 +0200
+++ b/src/pyams_form/widget/__init__.py	Tue Jul 17 18:02:48 2018 +0200
@@ -25,12 +25,13 @@
     IColorWidget, IHTMLWidget, ISelect2Widget, ITextLineListWidget, ISEOTextLineWidget, IActionWidget
 from pyams_form.schema import IResetButton, ICloseButton, IActionButton
 from pyams_skin.interfaces.tinymce import ITinyMCEConfiguration
+from pyams_utils.interfaces.data import IObjectData
 from pyams_utils.schema import IColorField, IHTMLField, ITextLineListField
 from pyramid.interfaces import IRequest
 from z3c.form.interfaces import INPUT_MODE, DISPLAY_MODE, IFieldWidget, IButtonAction, IWidgetLayoutTemplate, \
-    IDataConverter
+    IDataConverter, NO_VALUE
 from zope.pagetemplate.interfaces import IPageTemplate
-from zope.schema.interfaces import IDate, IDatetime, ITime, IChoice
+from zope.schema.interfaces import IDate, IDatetime, ITime, IChoice, IList, ITuple, ISet
 
 # import packages
 from pyams_utils.adapter import adapter_config
@@ -45,7 +46,7 @@
 from z3c.form.button import ButtonAction
 from z3c.form.converter import BaseDataConverter, DatetimeDataConverter as BaseDatetimeDataConverter
 from z3c.form.widget import FieldWidget, WidgetTemplateFactory, WidgetLayoutFactory
-from zope.interface import implementer_only, directlyProvides, Interface
+from zope.interface import implementer, implementer_only, directlyProvides, Interface
 from zope.schema.fieldproperty import FieldProperty
 
 from pyams_form import _
@@ -389,6 +390,60 @@
     return FieldWidget(field, Select2Widget(request))
 
 
+@widgettemplate_config(mode=INPUT_MODE, template='templates/hidden-select-input.pt', layer=IFormLayer)
+@implementer(IObjectData)
+class HiddenSelect2Widget(Select2Widget):
+    """Hidden select2 widget
+
+    Widget values are provided through IObjectData
+    """
+
+    def extract(self, default=NO_VALUE):
+        if self.name not in self.request and self.name + '-empty-marker' in self.request:
+            return []
+        value = self.request.get(self.name, default)
+        if value != default:
+            if not isinstance(value, (set, tuple, list)):
+                value = set(value.split('|'))
+            # do some kind of validation, at least only use existing values
+            for token in value:
+                if token == self.noValueToken:
+                    continue
+                try:
+                    self.terms.getTermByToken(token)
+                except LookupError:
+                    return default
+        return value
+
+    @property
+    def values(self):
+        return '|'.join(self.value or '')
+
+    @property
+    def values_map(self):
+        result = {}
+        terms = self.terms
+        [result.update({value: terms.getTermByToken(value).title}) for value in self.value or ()]
+        return json.dumps(result)
+
+
+def HiddenSelect2FieldWidget(field, request):
+    return FieldWidget(field, HiddenSelect2Widget(request))
+
+
+@adapter_config(context=(IList, HiddenSelect2Widget), provides=IDataConverter)
+@adapter_config(context=(ITuple, HiddenSelect2Widget), provides=IDataConverter)
+@adapter_config(context=(ISet, HiddenSelect2Widget), provides=IDataConverter)
+class HiddenSelect2DataConverter(BaseDataConverter):
+    """Hidden select2 data converter"""
+
+    def toWidgetValue(self, value):
+        return value or ()
+
+    def toFieldValue(self, value):
+        return set(value or ())
+
+
 #
 # TextLineList widget
 #
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_form/widget/templates/hidden-select-input.pt	Tue Jul 17 18:02:48 2018 +0200
@@ -0,0 +1,38 @@
+<label class="input bordered with-icon"
+	   tal:omit-tag="view/required" i18n:domain="onf_website">
+	<i class="icon-append fa fa-trash-o text-primary hint opaque"
+		title="Clear selected values" i18n:attributes="title"
+		tal:omit-tag="view/required"
+		data-ams-hint-gravity="se"
+		data-ams-click-handler="MyAMS.helpers.select2ClearSelection"
+		tal:attributes="data-ams-select2-target view/name"></i>
+	<div class="select2-parent"
+		 tal:omit-tag="view/required">
+		<input type="hidden" autocomplete="off"
+				class="select2"
+				data-ams-select2-separator="|"
+				tal:attributes="id view/id;
+								name string:${view/name};
+								class string:${view/klass} select2;
+								style view/style;
+								title view/title;
+								value view/values;
+								lang view/lang;
+								onclick view/onclick;
+								ondblclick view/ondblclick;
+								onmousedown view/onmousedown;
+								onmouseup view/onmouseup;
+								onmouseover view/onmouseover;
+								onmousemove view/onmousemove;
+								onmouseout view/onmouseout;
+								onkeypress view/onkeypress;
+								onkeydown view/onkeydown;
+								onkeyup view/onkeyup;
+								disabled view/disabled;
+								tabindex view/tabindex;
+								onchange view/onchange;
+								data-ams-data tales:object_data(view);
+								data-ams-select2-values view/values_map;
+								data-ams-select2-multiple python:'true' if view.multiple else None;" />
+	</div>
+</label>