Source code for pyquickhelper.ipythonhelper.html_forms

"""
Some functions to interact better with Notebook


:githublink:`%|py|5`
"""

import re

_reg_var = re.compile("^[a-zA-Z_]([a-zA-Z_0-9]*)$")


[docs]def open_html_form(params, title='', key_save="", style="background-color:gainsboro; padding:2px; border:0px;", raw=False, hook=None): """ The function displays a form onto a notebook, it requires a notebook to be open. :param params: dictionary of parameters (see comment below) :param title: titre of the added box :param style: style of the form :param key_save: name of the variable to add to the notebook (as a dictionary) :param raw: returns the raw HTML and not ``HTML( text )`` :param hook: an instruction as a string which will be executed if the button is clicked (None for none) :return: HTML The code comes from `IPython Notebook: Javascript/Python Bi-directional Communication <https://jakevdp.github.io/blog/2013/06/01/ipython-notebook-javascript-python-communication/>`_. When the notebook is converted into a HTML document, the values in the form do not appear. This behaviour is expected in case one of the field contains a password. On a notebook, it gives the following result: .. exref:: :title: Open a add a form in a notebook to ask parameters to a user .. image:: images/form.png Cell 1:: from pyquickhelper.ipythonhelper import open_html_form params = { "module":, "version":"v..." } open_html_form (params, title="try the password *", key_save="form1") Cell 2:: print(form1) We can execute a simple action after the button *Ok* is pressed. This second trick comes from `this notebook <https://raw.githubusercontent.com/fluxtream/fluxtream-ipy/master/ Communication%20between%20kernel%20and%20javascript%20in%20iPython%202.0.ipynb>`_. The code displays whatever comes from function ``custom_action`` in this case. You should return ``""`` to display nothing. :: def custom_action(x): x["combined"] = x["first_name"] + " " + x["last_name"] return x params = { "first_name":"", "last_name":"" } open_html_form(params, title="enter your name", key_save="my_address", hook="custom_action(my_address)") The function generates javascript based on the keys the dictionary ``params`` contains. The keys must follows the same as a javascript identifier (no space). :githublink:`%|py|66` """ global _reg_var for k in params: if not _reg_var.match(k): raise KeyError( # pragma: no cover "keys in params must look like a variable, it is not the case for " "'{}'.".format(k)) row = """<br />{0} <input type="{3}" id="{2}{0}" value="{1}" size="80" />""" rows = ["""<div style="{0}"><b>{1}</b>""".format(style, title)] for k, v in sorted(params.items()): if k.startswith("password"): typ = "password" else: typ = "text" rows.append(row.format(k, "" if v is None else str(v), key_save, typ)) rows.append( """<br /><button onclick="set_value{0}()">Ok</button></div>""".format(key_save)) if hook is not None: rows.append("<div id='out%s'></div>" % key_save.replace("_", "")) rows.append("""<script type="text/Javascript">""") rows.append("function %scallback(msg) {" % key_save) rows.append(" var ret = msg.content.data['text/plain'];") rows.append(" $('#out%s').text(ret);" % key_save.replace("_", "")) rows.append("}") rows.append("function set_value__KEY__(){".replace("__KEY__", key_save)) rows.append(" command='%s = {' ;" % key_save) for k, v in sorted(params.items()): rows.append( """ var {0}{1}var_value = document.getElementById('{0}{1}').value;""".format(key_save, k)) rows.append(""" command += '"{0}":"' + """.format(k) + "{0}{1}var_value".format(key_save, k) + """ + '",';""") rows.append(""" command += '}';""") rows.append(""" var kernel = IPython.notebook.kernel;""") rows.append(""" kernel.execute(command);""") if hook is not None: rows.append(""" kernel.execute('%s', {iopub: {output: %scallback}}, {silent: false});""" % ( hook, key_save)) rows.append("""}""") rows.append("</script>") text = "\n".join(rows) if raw: return text from IPython.display import HTML # pragma: no cover return HTML(text) # pragma: no cover