yafowil.widget.autocomplete 2.0.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,118 @@
1
+ from yafowil.base import factory
2
+ from yafowil.utils import entry_point
3
+ import os
4
+ import webresource as wr
5
+
6
+
7
+ resources_dir = os.path.join(os.path.dirname(__file__), 'resources')
8
+
9
+
10
+ ##############################################################################
11
+ # Default
12
+ ##############################################################################
13
+
14
+ # webresource ################################################################
15
+
16
+ resources = wr.ResourceGroup(
17
+ name='yafowil.widget.autocomplete',
18
+ directory=resources_dir,
19
+ path='yafowil-autocomplete'
20
+ )
21
+ resources.add(wr.ScriptResource(
22
+ name='yafowil-autocomplete-js',
23
+ directory=os.path.join(resources_dir, 'default'),
24
+ path='yafowil-autocomplete/default',
25
+ depends='jquery-js',
26
+ resource='widget.js',
27
+ compressed='widget.min.js'
28
+ ))
29
+ resources.add(wr.StyleResource(
30
+ name='yafowil-autocomplete-css',
31
+ directory=os.path.join(resources_dir, 'default'),
32
+ path='yafowil-autocomplete/default',
33
+ resource='widget.min.css'
34
+ ))
35
+
36
+ # B/C resources ##############################################################
37
+
38
+ js = [{
39
+ 'group': 'yafowil.widget.autocomplete.common',
40
+ 'resource': 'default/widget.js',
41
+ 'order': 21,
42
+ }]
43
+ css = [{
44
+ 'group': 'yafowil.widget.autocomplete.common',
45
+ 'resource': 'default/widget.min.css',
46
+ 'order': 21,
47
+ }]
48
+
49
+
50
+ ##############################################################################
51
+ # Bootstrap 5
52
+ ##############################################################################
53
+
54
+ # webresource ################################################################
55
+ bootstrap5_resources = wr.ResourceGroup(
56
+ name='yafowil.widget.autocomplete',
57
+ directory=resources_dir,
58
+ path='yafowil-autocomplete'
59
+ )
60
+ bootstrap5_js = wr.ScriptResource(
61
+ name='yafowil-autocomplete-js',
62
+ directory=os.path.join(resources_dir, 'bootstrap5'),
63
+ path='yafowil-autocomplete/bootstrap5',
64
+ depends='jquery-js',
65
+ resource='widget.js',
66
+ compressed='widget.min.js'
67
+ )
68
+ bootstrap5_resources.add(bootstrap5_js)
69
+ bootstrap5_resources.add(wr.StyleResource(
70
+ name='yafowil-autocomplete-css',
71
+ directory=os.path.join(resources_dir, 'bootstrap5'),
72
+ path='yafowil-autocomplete/bootstrap5',
73
+ resource='widget.min.css'
74
+ ))
75
+
76
+ # B/C resources ##############################################################
77
+
78
+ bootstrap5_css = [{
79
+ 'group': 'yafowil.widget.autocomplete.common',
80
+ 'resource': 'bootstrap5/widget.min.css',
81
+ 'order': 20,
82
+ }]
83
+
84
+
85
+ ##############################################################################
86
+ # Registration
87
+ ##############################################################################
88
+
89
+ @entry_point(order=10)
90
+ def register():
91
+ from yafowil.widget.autocomplete import widget # noqa
92
+
93
+ widget_name = 'yafowil.widget.autocomplete'
94
+
95
+ # Default
96
+ factory.register_theme(
97
+ 'default',
98
+ widget_name,
99
+ resources_dir,
100
+ js=js,
101
+ css=css
102
+ )
103
+ factory.register_resources('default', widget_name, resources)
104
+
105
+ # Bootstrap 5
106
+ factory.register_theme(
107
+ ['bootstrap5'],
108
+ widget_name,
109
+ resources_dir,
110
+ js=bootstrap5_js,
111
+ css=bootstrap5_css
112
+ )
113
+
114
+ factory.register_resources(
115
+ ['bootstrap5'],
116
+ widget_name,
117
+ bootstrap5_resources
118
+ )
@@ -0,0 +1,275 @@
1
+ from yafowil.base import factory
2
+ from yafowil.compat import IS_PY2
3
+ import json
4
+
5
+
6
+ if IS_PY2:
7
+ from urlparse import urlparse
8
+ from urlparse import parse_qs
9
+ else:
10
+ from urllib.parse import urlparse
11
+ from urllib.parse import parse_qs
12
+
13
+
14
+ lipsum = """Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
15
+ eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
16
+ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
17
+ consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
18
+ dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident,
19
+ sunt in culpa qui officia deserunt mollit anim id est laborum."""
20
+ lipsum = sorted(set(lipsum.lower().replace('.', '').replace(',', '').split()))
21
+
22
+
23
+ def json_response(url):
24
+ purl = urlparse(url)
25
+ qs = parse_qs(purl.query)
26
+ data = json_data(qs.get('term', [''])[0])
27
+ return {
28
+ 'body': json.dumps(data),
29
+ 'header': [('Content-Type', 'application/json')]
30
+ }
31
+
32
+
33
+ def json_data(term):
34
+ data = lipsum
35
+ if term:
36
+ data = [_ for _ in data if _.startswith(term)]
37
+ return data
38
+
39
+
40
+ actions_source = [
41
+ {
42
+ 'id': 'default',
43
+ 'title': 'Default Suggestion'
44
+ },
45
+ {
46
+ 'id': 'custom',
47
+ 'title': 'Custom Alert Item',
48
+ 'ignore_filter': True,
49
+ 'factory': 'yafowil_demo.CustomSuggestion'
50
+ },
51
+ 'String Suggestion'
52
+ ]
53
+
54
+
55
+ def json_response_actions(url):
56
+ purl = urlparse(url)
57
+ qs = parse_qs(purl.query)
58
+ data = actions_json_data(qs.get('term', [''])[0])
59
+ return {
60
+ 'body': json.dumps(data),
61
+ 'header': [('Content-Type', 'application/json')]
62
+ }
63
+
64
+
65
+ def actions_json_data(term):
66
+ filtered_data = []
67
+
68
+ for item in actions_source:
69
+ if isinstance(item, dict):
70
+ title = item['title']
71
+ if title.lower().startswith(term.lower()) or \
72
+ ('ignore_filter' in item and item['ignore_filter'] == True):
73
+ filtered_data.append(item)
74
+ else:
75
+ if item.lower().startswith(term.lower()):
76
+ filtered_data.append(item)
77
+ return filtered_data
78
+
79
+
80
+
81
+ DOC_STATIC = """\
82
+ Autocomplete with static vocabulary
83
+ -----------------------------------
84
+
85
+ Autocomplete can make use of a static vocabulary source. Here words of blind
86
+ text Lorem Ipsum are used. First the static list of words is generated
87
+
88
+ .. code-block:: python
89
+
90
+ lipsum = '''Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
91
+ eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
92
+ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
93
+ commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit
94
+ esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
95
+ cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id
96
+ est laborum.'''
97
+ lipsum = sorted(set(lipsum.lower().replace('.', '').replace(',', '').split()))
98
+
99
+ Next, the field is defined as
100
+
101
+ .. code-block:: python
102
+
103
+ field = factory('#field:autocomplete', props={
104
+ 'label': 'Enter some text (local, lorem ipsum)',
105
+ 'value': '',
106
+ 'source': lipsum,
107
+ })
108
+ """
109
+
110
+ DOC_JSON = """\
111
+ Autocomplete with dynamic json vocabulary
112
+ -----------------------------------------
113
+
114
+ Instead of static lists autocomplete may ask the server for a list of words
115
+ matching a given term. The source is a string and as such interpreted as a
116
+ absolute or relative url
117
+
118
+ .. code-block:: python
119
+
120
+ field = factory('#field:autocomplete', props={
121
+ 'label': 'Enter some text (remote listdir)',
122
+ 'value': '',
123
+ 'source': 'yafowil.widget.autocomplete.json',
124
+ 'minLength': 1,
125
+ })
126
+
127
+ The server answers with a JSON response, here the example does it using WSGI
128
+ and ``webob`` way. This code needs modification depending on the framework
129
+ used
130
+
131
+ .. code-block:: python
132
+
133
+ def json_response(environ, start_response):
134
+ data = lipsum
135
+ if environ['QUERY_STRING'].startswith('term='):
136
+ qsts = environ['QUERY_STRING'][5:]
137
+ data = [_ for _ in data if _.startswith(qsts)]
138
+ response = Response(content_type='application/json',
139
+ body=json.dumps(data))
140
+ return response(environ, start_response)
141
+ """
142
+
143
+ DOC_ACTIONS = """\
144
+ Suggestion Factories and Data types
145
+ -----------------------------------
146
+
147
+ Remote Autocomplete widgets may receive dict-like items. The key
148
+ of the currently selected item will be available in a hidden input field.
149
+
150
+ This also allows the Autocomplete Widget to initialize Suggestions using factories.
151
+ Setting the 'ignore_filter' flag won't validate a Suggestion client-side,
152
+ as long as it is present in the data returned from server.
153
+
154
+ Item types can be mixed and matched in one widget. Make sure to adjust your
155
+ backend validation method for filtering multiple types.
156
+
157
+ The following example shows how to extend or create your own Suggestion class
158
+ based on yafowil.widget.autocomplete:
159
+
160
+ .. code-block:: js
161
+
162
+ window.yafowil_demo = { // your desired path
163
+ CustomSuggestion: class CustomSuggestion extends window.yafowil_autocomplete.AutocompleteSuggestion {
164
+
165
+ constructor(widget, source, val) {
166
+ super(widget, source, val);
167
+ }
168
+
169
+ select() {
170
+ super.select();
171
+ alert('The Suggestion has been selected.');
172
+ }
173
+
174
+ compile() {
175
+ super.compile();
176
+ this.elem.css('background-color', '#ffe00057');
177
+ }
178
+ }
179
+ }
180
+
181
+ Your JSON data should return data formatted similar to the following example:
182
+
183
+ .. code-block:: json
184
+
185
+ [
186
+ {
187
+ 'id': 'default',
188
+ 'title': 'Default Suggestion'
189
+ },
190
+ {
191
+ 'id': 'custom',
192
+ 'title': 'Custom Alert Item',
193
+ 'ignore_filter': True,
194
+ 'factory': 'yafowil_demo.CustomSuggestion'
195
+ },
196
+ 'String Suggestion'
197
+ ]
198
+
199
+ Now initialize your widget:
200
+
201
+ .. code-block:: python
202
+
203
+ field = factory('#field:autocomplete', props={
204
+ 'label': 'Enter some text or select an Action',
205
+ 'value': '',
206
+ 'source': 'yafowil.widget.autocomplete_actions.json',
207
+ 'minLength': 1,
208
+ })
209
+
210
+ """
211
+
212
+ DOC_DISPLAY = """\
213
+ Display Mode
214
+ ------------
215
+
216
+ The widget's display mode renders the widget value inside an uneditable div.
217
+
218
+ The wrapper div can receive additional classes via the ``display_class``
219
+ widget attribute.
220
+
221
+ .. code-block:: python
222
+
223
+ field = factory('#field:autocomplete', mode='display', value='Lorem', props={
224
+ 'label': 'Display Mode',
225
+ 'source': lipsum,
226
+ # 'display_class': 'my_additional_class'
227
+ })
228
+ """
229
+
230
+
231
+
232
+ def get_example():
233
+ static_ac = factory('#field:autocomplete', name='static', props={
234
+ 'label': 'Enter some text (local, lorem ipsum)',
235
+ 'source': lipsum,
236
+ })
237
+ json_ac = factory('#field:autocomplete', name='json', props={
238
+ 'label': 'Enter some text (remote listdir)',
239
+ 'value': '',
240
+ 'source': 'yafowil.widget.autocomplete.json',
241
+ 'minLength': 1,
242
+ })
243
+ actions_ac = factory('#field:autocomplete', name='actions', props={
244
+ 'label': 'Enter some text or select an Action',
245
+ 'value': '',
246
+ 'source': 'yafowil.widget.autocomplete_actions.json',
247
+ 'minLength': 1,
248
+ })
249
+ display_ac = factory('#field:autocomplete', name='display', mode='display',
250
+ value='Lorem', props={
251
+ 'label': 'Display Mode',
252
+ 'source': lipsum,
253
+ })
254
+ routes = {
255
+ 'yafowil.widget.autocomplete.json': json_response,
256
+ 'yafowil.widget.autocomplete_actions.json': json_response_actions,
257
+ }
258
+ return [{
259
+ 'widget': static_ac,
260
+ 'doc': DOC_STATIC,
261
+ 'title': 'Static autocomplete',
262
+ }, {
263
+ 'widget': json_ac,
264
+ 'routes': routes,
265
+ 'doc': DOC_JSON,
266
+ 'title': 'JSON data autocomplete',
267
+ }, {
268
+ 'widget': actions_ac,
269
+ 'doc': DOC_ACTIONS,
270
+ 'title': 'Suggestion Factories and Data types',
271
+ }, {
272
+ 'widget': display_ac,
273
+ 'doc': DOC_DISPLAY,
274
+ 'title': 'Display Mode',
275
+ }]