@@ -71,7 +71,9 @@ read the following articles for more information:
7171Blocking confirm model
7272^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7373
74- .. collapse :: Code
74+ The following code uses the lock mechanism to make the button callback function synchronous:
75+
76+ .. collapse :: Click to expand the code
7577
7678 .. exportable-codeblock ::
7779 :name: cookbook-confirm-model
@@ -115,6 +117,105 @@ Blocking confirm model
115117 res = confirm('Confirm', 'You have 5 seconds to make s choice', timeout=5)
116118 output.put_text("Your choice is:", res)
117119
120+ Input in the popup
121+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
122+ .. https://github.com/pywebio/PyWebIO/discussions/132
123+
124+ In the following code, we define a ``popup_input() `` function, which can be used to get input in popup:
125+
126+ .. collapse :: Click to expand the code
127+
128+ .. exportable-codeblock ::
129+ :name: cookbook-redirect-stdout
130+ :summary: Redirect stdout to PyWebIO
131+
132+ import threading
133+
134+
135+ def popup_input(pins, names, title='Please fill out the form'):
136+ """Show a form in popup window.
137+
138+ :param list pins: pin output list.
139+ :param list pins: pin name list.
140+ :param str title: model title.
141+ :return: return the form as dict, return None when user cancel the form.
142+ """
143+ if not isinstance(pins, list):
144+ pins = [pins]
145+
146+ event = threading.Event()
147+ confirmed_form = None
148+
149+ def onclick(val):
150+ nonlocal confirmed_form
151+ confirmed_form = val
152+ event.set()
153+
154+ pins.append(put_buttons([
155+ {'label': 'Submit', 'value': True},
156+ {'label': 'Cancel', 'value': False, 'color': 'danger'},
157+ ], onclick=onclick))
158+ popup(title=title, content=pins, closable=False)
159+
160+ event.wait()
161+ close_popup()
162+ if not confirmed_form:
163+ return None
164+
165+ from pywebio.pin import pin
166+ return {name: pin[name] for name in names}
167+
168+
169+ from pywebio.pin import put_input
170+
171+ result = popup_input([
172+ put_input('name', label='Input your name'),
173+ put_input('age', label='Input your age', type="number")
174+ ], names=['name', 'age'])
175+ put_text(result)
176+
177+ The code uses :doc: `pin module </pin >` to add input widgets to popup window,
178+ and uses the lock mechanism to wait the form buttons to be clicked.
179+
180+
181+ Redirect stdout to PyWebIO application
182+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
183+ .. https://github.com/pywebio/PyWebIO/discussions/21
184+
185+ The following code shows how to redirect stdout of python code and subprocess to PyWebIO application:
186+
187+ .. collapse :: Click to expand the code
188+
189+ .. exportable-codeblock ::
190+ :name: cookbook-redirect-stdout
191+ :summary: Redirect stdout to PyWebIO
192+
193+ import io
194+ import time
195+ import subprocess # ..doc-only
196+ from contextlib import redirect_stdout
197+
198+ # redirect `print() ` to pywebio
199+ class WebIO(io.IOBase):
200+ def write(self, content):
201+ put_text(content, inline=True)
202+
203+ with redirect_stdout(WebIO()):
204+ for i in range(10):
205+ print(i, time.time())
206+ time.sleep(0.2)
207+
208+ ## ----
209+ import subprocess # ..demo-only
210+ # redirect a subprocess' stdout to pywebio
211+ process = subprocess.Popen("ls -ahl", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
212+ while True:
213+ output = process.stdout.readline()
214+ if output == '' and process.poll() is not None:
215+ break
216+ if output:
217+ put_text(output.decode('utf8'), inline=True)
218+
118219
119220
120221Web application related
@@ -166,3 +267,65 @@ Add the following code to the beginning of your PyWebIO application main functio
166267
167268 session.run_js('WebIO._state.CurrentSession.on_session_close(()=>{setTimeout(()=>location.reload(), 4000})')
168269
270+ Cookie and localStorage manipulation
271+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
272+ .. https://github.com/pywebio/PyWebIO/discussions/99
273+
274+ You can use `pywebio.session.run_js() ` and `pywebio.session.eval_js() ` to deal with cookies or localStorage with js.
275+
276+ ``localStorage `` manipulation:
277+
278+ .. exportable-codeblock ::
279+ :name: cookbook-localStorage
280+ :summary: ``localStorage `` manipulation
281+
282+ set_localstorage = lambda key, value: run_js("localStorage.setItem(key, value)", key=key, value=value)
283+ get_localstorage = lambda key: eval_js("localStorage.getItem(key)", key=key)
284+
285+ set_localstorage('hello', 'world')
286+ val = get_localstorage('hello')
287+ put_text(val)
288+
289+
290+ Cookie manipulation:
291+
292+ .. collapse :: Click to expand the code
293+
294+ .. exportable-codeblock ::
295+ :name: cookbook-cookie
296+ :summary: Cookie manipulation
297+
298+ # https://stackoverflow.com/questions/14573223/set-cookie-and-get-cookie-with-javascript
299+ run_js("""
300+ window.setCookie = function(name,value,days) {
301+ var expires = "";
302+ if (days) {
303+ var date = new Date();
304+ date.setTime(date.getTime() + (days*24*60*60*1000));
305+ expires = "; expires=" + date.toUTCString();
306+ }
307+ document.cookie = name + "=" + (value || "") + expires + "; path=/";
308+ }
309+ window.getCookie = function(name) {
310+ var nameEQ = name + "=";
311+ var ca = document.cookie.split(';');
312+ for(var i=0;i < ca.length;i++) {
313+ var c = ca[i];
314+ while (c.charAt(0)==' ') c = c.substring(1,c.length);
315+ if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
316+ }
317+ return null;
318+ }
319+ """)
320+
321+ def setcookie(key, value, days=0):
322+ run_js("setCookie(key, value, days)", key=key, value=value, days=days)
323+
324+ def getcookie(key):
325+ return eval_js("getCookie(key)", key=key)
326+
327+ setcookie('hello', 'world')
328+ val = getcookie('hello')
329+ put_text(val)
330+
331+
0 commit comments