<jupyter_start><jupyter_text>IPython Display - componentes web> Componentes web para agregar interactividad a Jupyter Notebook/Lab.- featured: false- hide: false- toc: true- badges: true- comments: true- categories: [jupyter, rise]- image: images/preview/jupyter.png  IPython.Display - la parte webEn IPython.display existen 23 clases que son muy prácticas para agregar interactividad a Jupyter Notebook/Lab.**Acá probamos únicamente 3 que se relacionan con la web: IFrame, HTML, Javascript.**  1. Antes de: principales errores 1.1 Usando display generosamente Mi principal aprendizaje es que IPython.display genera **objetos** de distintos tipos. Los objetos no se muestran o ejecutan por defecto. Si el objeto es el resultado de la celda, el objeto **si** se despliega o ejecuta. Si no es el resultado de la celda, no se muestra/ejecuta, a menos que se use el método display.   Diferencias entre hermanosJupyter Notebook, Jupyter Lab y Google Colab no son completamente similares. Hasta ahora, lo que he visto:* En Google Colab está IPython 5.0.0. No es lo mejor para evaluar javascript. De hecho, hay funciones que no existen: `alert` y `prompt` no están.Link interesante: https://colab.research.google.com/notebooks/snippets/advanced_outputs.ipynbscrollTo=iXZ0xoQd2kCe  2. Páginas web  2.1 IFrame```pythonIFrame(src,        width,        height,        **kwargs)```Permite insertar una página web como un IFrame (inline frame). La página debe permitirlo (no todas lo hacen). Por ejemplo, para insertar una encuesta o una referencia en un jupyter notebook o una presentación con RISE.Métodos o atributos del objeto creado:* `iframe`: String con la representación HTML del objeto. No es muy útil.<jupyter_code>from IPython.display import IFrame
IFrame("https://es.wikipedia.org/wiki/IFrame", width=800, height=400)<jupyter_output><empty_output><jupyter_text>Para más información, ver la documentación con `IFrame.?`  2.2 Javascript```pythonJavascript(data=None,            url=None,            filename=None,            lib=None,            css=None)```Carga el código javascript en la página. En el notebook, el elemento conteneder será `element`,y jQuery estará disponible. Contenido agregado a `element` serán visibles en la área de output.Métodos o atributos del objeto creado:* **metadata**: Atributo string con la metadata con la que fue creado el objeto.* **reaload**: Método para recargar el contenido del objeto, si fue creado desde url o archivo.<jupyter_code># Alert - no funciona en Google Colab
from IPython.display import Javascript
Javascript('alert("¡¡Tenemos javascript!!");')
# Console.log - funciona siempre
from IPython.display import Javascript
Javascript('console.log("¡¡Tenemos javascript!!");')
# Ejecutando javascript
from IPython.display import Javascript
js_str = """
var a = 1;
console.log("JS1: a = "+a);
var b = 2;
console.log("JS1: b = " + b);
console.log("JS1: a+b = " + (a+b));
"""
Javascript(js_str)
# Ejecutando javascript
from IPython.display import Javascript, display
js_str_1 = """
var a = 1;
console.log("JS2: a ="+a);
"""
js_str_2 = """
var b = 2;
console.log("JS2: b =" + b);
console.log("JS2: a+b=" + (a+b));
"""
js_1 = Javascript(js_str_1)
js_2 = Javascript(js_str_2)
display(js_1, js_2)
from IPython.display import Javascript
Javascript?
from IPython.display import Javascript
print("Methods:")
print(sorted([f for f in dir(Javascript) if not f.startswith('_')]))<jupyter_output><empty_output><jupyter_text>2.3 HTML```pythonHTML(data=None,      url=None,      filename=None,      metadata=None)```Observación/Consejos: * No incluir secciones de ``, `` o ``.* El Javascript vive en la celda de notebook, las variables no se traspasan de una celda a otra. Ver los ejemplos al final.* En Google Colab algunas funciones de javascript no están disponibles, en particular 'alert'.Métodos o atributos del objeto creado:* `metadata`: String con la metadata con la que fue creado el objeto.* `reaload()`: Método para recargar el contenido del objeto, si fue creado desde url o archivo.<jupyter_code># Ejemplo 1: HTML simple
from IPython.display import HTML
HTML("<div style='background-color:lightblue'>Este es un ejemplo.</div>")
# Ejemplo 2: HTML con javascript
# Ver resultado con la consola de javascript
from IPython.display import HTML
my_html = """
<script>
function button_action(value){
  var msg = 'La variable tiene valor '+ value;
  console.log(msg);
  alert(msg);
};
</script>

<div> 
Variable: 
<input type='text' id='my_input_form' value='42'> 
<button onclick='button_action(document.getElementById("my_input_form").value)'>Click</button>
</div>
"""
HTML(data=my_html)
# Ejemplo 3: filename
from IPython.display import HTML
my_filename = "html/ejemplo.html"
HTML(filename=my_filename)
# Ejemplo 4: url
from IPython.display import HTML
my_url = "https://raw.githubusercontent.com/sebastiandres/2021-05-IPython-display/master/html/ejemplo.html"
HTML(url=my_url)
# Ejecutando javascript desde HTML
from IPython.display import HTML
my_html = """
<script>
var a = 1;
console.log("HTML: a ="+a);
</script>
"""
HTML(my_html)<jupyter_output><empty_output><jupyter_text>Más información<jupyter_code>from IPython.display import HTML
HTML?
from IPython.display import HTML
print("Methods:")
print(sorted([f for f in dir(HTML) if not f.startswith('_')]))<jupyter_output><empty_output><jupyter_text>3. Experimentos  3.1 Experimento HTML 1:Valores de variables no se traspasan de una celda a otra. Definiremos `a`en la primera celda, y trataremos de imprimir el valor de `a` en la celda siguiente.<jupyter_code># Definir a
from IPython.display import HTML
my_html = """
<script>
var num = 42;
console.log("HTML1A: num = " + num);
</script>
"""
HTML(my_html)
# Imprimir a
from IPython.display import Javascript
my_html = """
<script>
var b = 2;
console.log("HTML1B1: num =" + num);
console.log("HTML1B2: b =" + b);
console.log("HTML1B3: num+b=" + (num+b));
</script>
"""
HTML(my_html)<jupyter_output><empty_output><jupyter_text>Experimento HTML 2:Colocando varios scripts en un único html: si funciona.<jupyter_code># Test: Several scripts, all in one HTML
from IPython.display import HTML
my_html = """
<script>
var a = 1;
console.log("HTML2A: a = "+a);
</script>

<script>
var b = 2;
console.log("HTML2B: b = "+b);
</script>

<script>
console.log("HTML2C: a+b = "+(a+b));
</script>
"""
HTML(my_html)<jupyter_output><empty_output><jupyter_text>Experimento HTML 3:Ejecutando varios HTMLs por separado.<jupyter_code># Several HTML
from IPython.display import HTML, display
my_html = """
<script>
var a = 1;
console.log("HTM3: a = "+a);
</script>
"""
h1 = HTML(my_html)
my_html = """
<script>
var b = 2;
console.log("HTML3: b = "+b);
</script>
"""
h2 = HTML(my_html)
my_html = """
<script>
console.log("HTML3: a+b = "+(a+b));
</script>
"""
h3 = HTML(my_html)
display(h1, h2, h3) # Hay que poner todos, sino solo muestra el último<jupyter_output><empty_output><jupyter_text>Experimento HTML 4:El hermano pobre RISE, ¿cómo hacer presentaciones con reveal.js?<jupyter_code>!cat body.html
from IPython.display import HTML, Javascript, display
HTML(filename="body.html")
from IPython.display import HTML, Javascript, display
my_path = "https://raw.githubusercontent.com/sebastiandres/2021-05-IPython-display/master/"
my_js = Javascript(url=my_path+"body.js", lib=my_path+"reveal.js", css=my_path+"reveal.css")
my_html = HTML(filename="body.html")
display(my_js)
display(my_html)
## Adding a css with js
from IPython.display import HTML, Javascript, display
my_js = """
var link = document.createElement('link');
link.rel = "stylesheet"; link.type = "text/css";
link.href = "reveal.css";
document.querySelector('head').appendChild(link);
"""
Javascript(my_js)<jupyter_output><empty_output><jupyter_text>Experimento JS 1:Ejecutando varios javascript por separado.<jupyter_code># Definir a
from IPython.display import Javascript
js_str_1 = """
var num = 42;
console.log("JS1A: num = " + num);
"""
Javascript(js_str_1)
# Imprimir a
from IPython.display import Javascript
js_str_2 = """
var num = 42;
var b = 2;
console.log("JS1B1: num = " + num);
console.log("JS1B2: b = " + b);
console.log("JS1B3: num+b = " + (num+b));
"""
Javascript(js_str_2)<jupyter_output><empty_output><jupyter_text>Experimento JS 2:Usando javascript (puro) para agregar elementos html de manera dinámica. Observación: No se usa html, sino sólo Javascript sobre el "element".<jupyter_code># Ejemplo 2
from IPython.display import Javascript
my_js = """
function button_action(value){
  console.log('La variable tiene valor '+ value);
};

element.append(`<div> 
Variable: 
<input type='text' id='my_input_form' value='42'> 
<button onclick='button_action(document.getElementById("my_input_form").value)'>Click</button>
</div>`);
"""
Javascript(my_js)<jupyter_output><empty_output><jupyter_text>Experimento JS 3:Usando javascript para graficar.**CURRENTLY NOT WORKING**<jupyter_code># Ejemplo 3: Una visualización con xkcd-chart
# https://github.com/timqian/chart.xkcd
from IPython.display import Javascript
my_js = """
  const svg = document.querySelector('.line-chart')

  new chartXkcd.Line(svg, {
    title: 'Monthly income of an indie developer',
    xLabel: 'Month',
    yLabel: '$ Dollars',
    data: {
      labels:['1', '2', '3', '4', '5', '6','7', '8', '9', '10'],
      datasets: [{
        label: 'Plan',
        data: [30, 70, 200, 300, 500 ,800, 1500, 2900, 5000, 8000],
      }, {
        label: 'Reality',
        data: [0, 1, 30, 70, 80, 100, 50, 80, 40, 150],
      }]
    },
    options: {}
  });
  
  element.append(`<svg class="line-chart"></svg>`)
"""
my_lib = "https://cdn.jsdelivr.net/npm/chart.xkcd@1/dist/chart.xkcd.min.js"
Javascript(data=my_js, lib=my_lib)<jupyter_output><empty_output><jupyter_text>Experimento JS 3:Usando javascript para graficar.**CURRENTLY NOT WORKING**<jupyter_code>from IPython.display import Javascript
# Link: https://github.com/timqian/chart.xkcd/blob/master/examples/index.js
my_url = "https://raw.githubusercontent.com/timqian/chart.xkcd/master/examples/index.js"
my_lib = "https://cdn.jsdelivr.net/npm/chart.xkcd@1/dist/chart.xkcd.min.js"
Javascript(url=my_url, lib=my_lib)
import IPython

js_code = \
'''
let message = "Hello world!";
//document.querySelector("#output-area").appendChild(document.createTextNode(message));
element.append(document.createTextNode(message));
'''

display(IPython.display.Javascript(js_code))
import IPython

js_code = \
'''
var a = prompt("Hello", "Sebas");
alert(a);
'''

display(IPython.display.Javascript(js_code))
from IPython.display import HTML, Image

canvas_html = """
<canvas width=%d height=%d style="background-color:rgb(240,240,240)"></canvas>
<button>Guess Number</button>
<script>
var canvas = document.querySelector('canvas')
var ctx = canvas.getContext('2d')
ctx.lineWidth = %d
var button = document.querySelector('button')
var mouse = {x: 0, y: 0}
canvas.addEventListener('mousemove', function(e) {
  mouse.x = e.pageX - this.offsetLeft
  mouse.y = e.pageY - this.offsetTop
})
canvas.onmousedown = ()=>{
  ctx.beginPath()
  ctx.moveTo(mouse.x, mouse.y)
  canvas.addEventListener('mousemove', onPaint)
}
canvas.onmouseup = ()=>{
  canvas.removeEventListener('mousemove', onPaint)
}
var onPaint = ()=>{
  ctx.lineTo(mouse.x, mouse.y)
  ctx.stroke()
}
var data = new Promise(resolve=>{
  button.onclick = ()=>{
    resolve(canvas.toDataURL('image/png'))
  }
})
</script>
"""
print(canvas_html % (280, 280, 10))

def draw(filename='drawing.png', w=280, h=280, line_width=10):
  display(HTML(canvas_html % (w, h, line_width)))

draw()
from IPython.display import HTML
HTML(filename="drawing.html")<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14183726131085497, 'fraction_numerical': 0.01814897643213487, 'mean_word_length': 5.363984674329502, 'pattern_counts': {'":': 0, '<': 89, '<?xml version=': 0, '>': 95, 'https://': 9, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '81197', 'license': 'Apache-2.0', 'n_tokens_mistral': 4356, 'n_tokens_neox': 4105, 'n_words': 1094, 'path': '_notebooks/2021-05-02-ipython-display-web.ipynb', 'repo_name': 'sebastiandres/blog', 'size': '11626'}