8. Problemas

8.1. Lenguajes de marcado

Problema

Indica con qué código HTML es necesario sustituir la cadena @1 para que el siguiente bloque HTML sea válido y corresponda a una tabla con dos filas (la primera de encabezado) y una columna.

1<table>
2  <thead><tr><td><em>Nombre del río</em>@1<td>Ebro</td></tr>
3</table>

Problema

Indica en qué orden colocar las líneas de HTML de más abajo para que el fragmento de código HTML resultante sea correcto y se visualice en un navegador aproximadamente como sigue, sin usar ninguna hoja de estilo adicional:

1<li>azul
2<ul>
3</section>
4</li>
5<section><h4>Colores
6</h4>
7</ul>

Una posible respuesta (incorrecta) tendría el formato 1,2,3,4,5,6,7.

Problema

Dibuja el árbol DOM correspondiente al siguiente documento HTML. Representa todos los nodos, incluyendo aquellos que representan secuencias de blancos.

 1<!doctype html>
 2<html lang="es"><head>
 3      <title>La historia interminable</title></head>
 4  <body><section><h2>La ciudad de los espectros</h2><p>Fújur se esforzó
 5  desesperadamente por encontrar otra vez el lugar en que Atreyu debía de haber
 6  caído al agua, pero hasta para un dragón blanco de la suerte es imposible
 7  descubrir en la espuma hirviente de un mar revuelto el puntito diminuto de un
 8  cuerpo que flota... o el de un ahogado en su fondo.</p><p>Sin embargo, Fújur
 9  no quiso renunciar.</p></section>
10</body>
11</html>

Problema

Considera los siguientes datos:

  • El carácter a (Latin small letter a, U+0061) en US-ASCII se repesenta como 61 en hexadecimal (01100001 en binario), igual que en ISO/IEC 8859 y que en UTF-8; en UTF-16 es FEFF0061 (o en binario 11111110 11111111 00000000 01100001).

  • El carácter á (Latin small letter a with acute, U+00E1) se representa en ISO/IEC 8859-15 como E1 y en UTF-8 como C3A1.

  • El carácter à se representa en ISO/IEC 8859-15 como C3.

  • El carácter ¡ se representa en ISO/IEC 8859-15 como A1.

Teniendo en cuenta los datos de las diapositivas anteriores, ¿cómo se ve un fichero de texto escrito en UTF-8 que contiene la cadena aáa en un editor de texto configurado para ISO/IEC 8859-15? ¿Cómo se ve un fichero de texto escrito en ISO/IEC 8859-15 que contiene la cadena aáa en un editor de texto configurado para UTF-8?

Problema

Indica con qué código HTML es necesario sustituir las marcas @1 y @2 para que el siguiente bloque de HTML sea válido.

1<div>
2  <img src="imagen.png" @1="diagrama de clases">
3  <span @2-paquete="es.ua.dai">compilado sin errores</span>
4</div>

Problema

¿Qué tamaño en bytes tiene en UTF-8 el carácter del avión (✈) si sabemos que con UTF-8 la cadena (sin las comillas) «Avión a reacción: ✈» ocupa 23 bytes? Nota: por si no se distingue bien, la cadena tiene 3 espacios en blanco.

Problema

Considera estos tres caracteres: , ü, $. Si sabemos que el kanji japonés (sushi) no ocupa dos caracteres en UTF-8, indica cuál de los caracteres de la lista hay que añadir a un fichero de texto codificado en UTF-8 que contenía inicialmente los caracteres «鮨sushi鮨ñamñam» (sin las comillas) para que el fichero pase a tener 21 bytes de tamaño. La respuesta no es ninguno.

Problema

Aunque en el idioma birmano es habitual usar los números arábigos, las cantidades pueden encontrarse también representadas con números que usan una grafía propia. Los números del 1 al 5 en esta grafía del birmano son: «၁», «၂», «၃», «၄» y «၅». El sistema de numeración usado es el indo-arábigo (el mismo que usamos nosotros) y, por lo tanto, el número 12345 se representa como «၁၂၃၄၅». Sin más información que la que has estudiado en la asignatura respecto al estándar Unicode, indica una cota inferior y una cota superior de la cantidad de bytes que son necesarios para representar en UTF-8 la cadena que representa el número «၁၂၂၄၂၄».

Problema

Indica con qué código HTML es necesario sustituir las marcas @1 y @2 para que el siguiente bloque de HTML sea válido.

1<section>
2    <span @2-color="yellow">NEW!</span>
3    <img src="rainbow.svg" @1="vector graphic">
4</section>

8.2. Lenguajes de estilo

Problema

Considera el siguiente fragmento de un documento HTML:

 1<body>
 2  <section>
 3    <header><h1>The Boy Who Lived</h1></header>
 4    <p>Mr. and Mrs. Dursley, of number four, Privet Drive,
 5      were proud to say that they were perfectly normal,
 6      thank you very much.</p>
 7    <p class="last">They were the last people you'd expect to
 8      be involved in anything strange or mysterious, because they
 9      just didn't hold with such nonsense.</p>
10  </section>
11</body>

Considera también los siguientes estilos de CSS:

 1p {
 2  color: red;
 3}
 4p.last {
 5  color: gray;
 6}
 7section > p {
 8  color: blueviolet;
 9}
10header h1 p {
11  color: green;
12}
13section {
14  color: lightskyblue;
15}
16p {
17  color: black;
18}

¿De qué color se muestra el párrafo que comienza por «They were the last people…»? ¿Y el párrafo anterior a ese? Indica como respuesta los dos colores separados por una coma.

Problema

Considera el siguiente fragmento de CSS:

1.a {font-weight: normal;}
2.a .b {color: blue;}
3.a .b #c {color: red;}
4.destaca {font-weight: bold;}

Indica con qué sustituir las dos arrobas (@1, @2) para que dado el siguiente fragmento de HTML el texto Privet Drive se muestre en negrita y color rojo. Usa la notación @1=...,@2=... para tu respuesta.

1<p class="a">El señor y la señora Dursley, que vivían en el
2número 4 de @1 Privet Drive @2, estaban orgullosos de decir
3que eran muy normales, afortunadamente.</p>

Problema

Dibuja de la forma más precisa que puedas cómo representaría un navegador el siguiente bloque de código. No es necesario que los colores o el tipo de letra coincidan. Todos los tamaños han de mantener de forma aproximada la misma proporcionalidad que tendrían en la ventana del navegador: decide cuál es el tamaño en papel de, por ejemplo, 10 píxeles, y mantén la escala en todos los elementos.

1<body>
2  <div id="peligrosas">
3    colacuerno
4    <div id="basilisco">basilisco</div>
5  </div>
6  <div id="hipogrifo">hipogrifo</div>
7<body>

Considera que se están aplicando los siguientes estilos:

 1* {
 2  margin: 0;
 3  padding: 0;
 4  box-sizing: border-box;
 5}
 6body {
 7  margin: 10px;
 8}
 9#peligrosas {
10  width: 200px;
11  border: 1px solid darkgray;
12  padding-left: 50px;
13  padding-bottom: 50px;
14}
15#basilisco {
16  width: 50px;
17}
18#hipogrifo {
19  width: 100px;
20  border: 1px dotted darkgray;
21  text-align: right;
22  padding-bottom: 50px;
23}

Problema

Considera el siguiente fragmento de un documento HTML:

1<body>
2  <h1>Lista</h1>
3  <section>
4    <article>artículo1</article>
5    <article>artículo2</article>
6  </section>
7</body>

Teníamos una hoja de estilo que asignaba estilos a cada elemento para que el documento se visualizara como sigue (el fondo gris representa la ventana del navegador):

Lamentablemente, las propiedades del fichero CSS se nos han borrado y solo nos han quedado las siguientes reglas vacías que únicamente tienen selector pero ninguna propiedad:

1h1, section, article {  }
2h1::after {  }
3h1 {  }
4article {  }

Indica en qué regla de las anteriores hay que colocar cada una de las siguientes propiedades CSS para que el documento HTML se vuelva a visualizar como antes:

  1. font-family:serif

  2. display:inline

  3. font-family:sans-serif

  4. content:": "

  5. font-style:italic

Para abreviar, usa una notación como la de la siguiente posible respuesta (incorrecta): h1, section, article {1} / h1::after {1;2} / h1 {3;4} / article {5}.

Problema

Dado el siguiente fragmento de un documento HTML, indica un selector que tenga menos de 10 caracteres y que permita seleccionar el párrafo que contiene la cadena dos:

 1<body>
 2  <header>
 3    <h1>a</h1>
 4  </header>
 5  <main id="principal" class="info-descripción act">
 6    <h2>b</h2>
 7    <p>uno</p>
 8    <p id="info-detalle" class="act">dos</p>
 9  </main>
10  <section>
11    <h2>c</h2>
12    <p>tres</p>
13    <p lang="ca" class="act">quatre</p>
14  </section>
15</body>

Problema

Indica la palabra con la que rellenar el hueco de la siguiente frase para que sea correcta: el selector #a[href="https://example.org"] es un selector compuesto que incluye un selector de _____ y un selector de identificador.

Problema

Dados los siguientes estilos de CSS:

1li {
2  display: inline;
3  margin: 0px 25px 0px 25px;
4  padding: 10px 50px 10px 0px;
5  border: 2px solid #000000;
6}

Dibuja de la forma más aproximada posible cómo representaría el navegador el siguiente fragmento de HTML. Comienza pintando un recuadro que represente la ventana del navegador.

1<p>Recuerdo cada varita que he vendido, Harry Potter.
2Cada una de las varitas.
3Y resulta que la cola de fénix de donde salió la pluma
4que está en tu varita dio otra pluma,</p>
5<ul>
6  <li>solo</li>
7  <li>una</li>
8  <li>más.</li>
9</ul>

Problema

Considera el siguiente fragmento de un documento HTML:

1<body>
2  <div class="cuadrados">
3    <div class="orange">naranja</div>
4    <div class="blue">azul</div>
5    <div class="lavender">lavanda</div>
6    <div class="palegreen">verde</div>
7  </div>
8</body>

Considera también los siguientes estilos de CSS:

 1.cuadrados {
 2  background: gainsboro;
 3  padding: 10px;
 4  margin-bottom: 20px;
 5}
 6.orange {
 7  background: orange;
 8  height: 100px;
 9  width: 100px;
10}
11.blue {
12  background: lightskyblue;
13  height: 100px;
14  width: 100px;
15  position: relative;
16  top: -100px;
17  left: 100px;
18}
19.lavender {
20  background: lavender;
21  height: 100px;
22  width: 100px;
23  position: relative;
24  top: -100px;
25}
26.palegreen {
27  background: palegreen;
28  height: 100px;
29  width: 100px;
30  position: relative;
31  @1
32}

Indica el código CSS por el que es necesario sustituir la marca @1 para que el fragmento HTML se muestre como sigue:

Considera que no hay otros estilos definidos que puedan entrar en conflicto con los que escribas.

Problema

Dibuja de la forma más precisa que puedas cómo representaría un navegador el siguiente bloque de código. No es necesario que los colores o el tipo de letra coincidan. Todos los tamaños han de mantener de forma aproximada la misma proporcionalidad que tendrían en la ventana del navegador: decide cuál es el tamaño en papel de, por ejemplo, 50 píxeles, y mantén la escala en todos los elementos.

1<div class="cuadrados">
2  <div class="blue">azul</div>
3  <div class="lavender">lavanda</div>
4</div>

Considera que se están aplicando los siguientes estilos:

 1* {
 2  margin: 0;
 3  box-sizing: border-box;
 4}
 5.cuadrados {
 6  padding: 10px;
 7  border: 1px solid darkgray;
 8  height: 200px;
 9  width: 200px;
10}
11.blue {
12  border: 1px dashed darkgray;
13  height: 50px;
14  width: 50px;
15  position: relative;
16  top: 100px;
17  left: 50px;
18}
19.lavender {
20  border: 1px solid darkgray;
21  height: 100px;
22  width: 100px;
23}

Problema

Dibuja de la forma más precisa que puedas cómo representaría un navegador el siguiente bloque de código. No es necesario que los colores o el tipo de letra coincidan. Todos los tamaños han de mantener de forma aproximada la misma proporcionalidad que tendrían en la ventana del navegador: decide cuál es el tamaño en papel de, por ejemplo, 50 píxeles, y mantén la escala en todos los elementos.

1<div class="cuadrados">
2  <div class="blue">azul</div>
3  <div class="lavender">lavanda</div>
4</div>

Considera que se están aplicando los siguientes estilos:

 1* {
 2  margin: 0;
 3  box-sizing: border-box;
 4}
 5.cuadrados {
 6  padding: 10px;
 7  border: 1px solid darkgray;
 8  position: relative;
 9  height: 200px;
10  width: 200px;
11}
12.blue {
13  border: 1px dashed darkgray;
14  height: 50px;
15  width: 50px;
16  position: absolute;
17  top: 50px;
18  left: 50px;
19}
20.lavender {
21  border: 1px solid darkgray;
22  height: 100px;
23  width: 100px;
24}

Problema

Considera el siguiente código de una página web:

 1<!doctype html>
 2<html lang="es">
 3  <head>
 4    <meta charset="utf-8">
 5    <title>Cuadrados</title>
 6    <style>
 7      .cuadrados {
 8        width: 500px;
 9        background: gainsboro;
10        padding: 10px;
11      }
12      .orange {
13        background: orange;
14        height: 100px;
15        width: 100px;
16      }
17      .blue {
18        background: lightskyblue;
19        height: 100px;
20        width: 100px;
21      }
22      .lavender {
23        background: lavender;
24        height: 100px;
25        width: 100px;
26      }
27      .lemonchiffon {
28        background: lemonchiffon;
29        height: 100px;
30        width: 100px;
31      }
32    </style>
33  </head>
34  <body>
35    <div class="cuadrados">
36      <div class="orange">naranja</div>
37      <div class="blue">azul</div>
38      <div class="lavender">lavanda</div>
39      <div class="lemonchiffon">lemonchiffon</div>
40    </div>
41  </body>
42</html>

La página anterior se muestra en el navegador como sigue:

Considera ahora una versión ligeramente diferente del código anterior:

 1<!doctype html>
 2<html lang="es">
 3  <head>
 4    <meta charset="utf-8">
 5    <title>Cuadrados del problema 4</title>
 6    <style>
 7      .cuadrados {
 8        width: 500px;
 9        background: gainsboro;
10        padding: 10px;
11      }
12      .orange {
13        background: orange;
14        height: 100px;
15        width: 100px;
16        position: relative;
17        left: @1;
18      }
19      .blue {
20        background: lightskyblue;
21        height: 100px;
22        width: 100px;
23        position: relative;
24        right: @2;
25      }
26      .lavender {
27        background: lavender;
28        height: 100px;
29        width: 100px;
30        position: relative;
31        left: @1;
32      }
33      .lemonchiffon {
34        background: lemonchiffon;
35        height: 100px;
36        width: 100px;
37        position: relative;
38        right: @2;
39      }
40    </style>
41  </head>
42  <body>
43    <div class="cuadrados">
44      <div class="orange">naranja</div>
45      <div class="blue">azul</div>
46      <div class="lavender">lavanda</div>
47      <div class="lemonchiffon">lemonchiffon</div>
48    </div>
49  </body>
50</html>

Indica con qué sustituir @1 y @2 en el código anterior para que el documento se muestre cómo sigue:

Como pista, recuerda que en el posicionamiento relativo un valor positivo de la propiedad right especifica la distancia que el límite derecho del elemento se ha de mover a la izquierda respecto a su posición normal; un valor negativo de la propiedad right especifica, al contrario, la distancia que el límite derecho del elemento se ha de mover a la derecha respecto a su posición normal. En el caso de la propiedad left un valor positivo representa un movimiento a la derecha de la caja y un valor negativo representa un movimiento a la izquierda.

Problema

Considera el siguiente código de una página web:

 1<!doctype html>
 2<html lang="es">
 3  <head>
 4    <meta charset="utf-8">
 5    <title>Cuadrados del problema 5</title>
 6    <style>
 7      .cuadrados {
 8        width: 500px;
 9        background: gainsboro;
10        padding: 10px;
11      }
12      .orange {
13        background: orange;
14        height: 100px;
15        width: 100px;
16        position: relative;
17        bottom: @1;
18      }
19      .blue {
20        background: lightskyblue;
21        height: 100px;
22        width: 100px;
23        position: relative;
24        bottom: @2;
25      }
26      .lavender {
27        background: lavender;
28        height: 100px;
29        width: 100px;
30        position: relative;
31        bottom: @3;
32      }
33      .lemonchiffon {
34        background: lemonchiffon;
35        height: 100px;
36        width: 100px;
37        position: relative;
38        bottom: @4;
39      }
40    </style>
41  </head>
42  <body>
43    <div class="cuadrados">
44      <div class="orange">naranja</div>
45      <div class="blue">azul</div>
46      <div class="lavender">lavanda</div>
47      <div class="lemonchiffon">lemonchiffon</div>
48    </div>
49  </body>
50</html>

Indica con qué sustituir @1, @2, @3 y @4 en el código anterior para que el documento se muestre cómo sigue:

Como pista, recuerda que en el posicionamiento relativo un valor positivo de la propiedad right especifica la distancia que el límite derecho del elemento se ha de mover a la izquierda respecto a su posición normal; un valor negativo de la propiedad right especifica, al contrario, la distancia que el límite derecho del elemento se ha de mover a la derecha respecto a su posición normal. En el caso de la propiedad left un valor positivo representa un movimiento a la derecha de la caja y un valor negativo representa un movimiento a la izquierda. Para este problema en concreto puedes adaptar la pista anterior sobre las propiedades left y right al caso de las propiedades top y bottom.

Problema

Considera el siguiente código de una página web:

 1<!doctype html>
 2<html lang="es">
 3  <head>
 4    <meta charset="utf-8">
 5    <title>Cuadrados del problema 6</title>
 6    <style>
 7      .cuadrados {
 8        width: 500px;
 9        height: 400px;
10        background: gainsboro;
11        padding: 10px;
12        position: @1;
13      }
14      .orange {
15        background: orange;
16        height: 100px;
17        width: 100px;
18        position: absolute;
19        top: 10px;
20        @2: 10px;
21      }
22      .blue {
23        background: lightskyblue;
24        height: 100px;
25        width: 100px;
26        position: absolute;
27        top: 110px;
28      }
29      .lavender {
30        background: lavender;
31        height: 100px;
32        width: 100px;
33        position: absolute;
34        top: 210px;
35      }
36      .lemonchiffon {
37        background: lemonchiffon;
38        height: 100px;
39        width: 100px;
40        position: @3;
41        top: @4;
42      }
43    </style>
44  </head>
45  <body>
46    <div class="cuadrados">
47      <div class="orange">naranja</div>
48      <div class="blue">azul</div>
49      <div class="lavender">lavanda</div>
50      <div class="lemonchiffon">lemonchiffon</div>
51    </div>
52  </body>
53</html>

Indica con qué sustituir @1, @2, @3 y @4 en el código anterior para que el documento se muestre cómo sigue:

Como pista, recuerda que en el posicionamiento absoluto la propiedad top especifica la distancia entre el límite superior del elemento y el límite superior de cierto elemento contenedor; si el valor es negativo, el límite superior de dicho elemento contenedor queda por debajo del límite superior del elemento contenido. De forma análoga, puedes deducir el propósito de las propiedades left, top o bottom.

Problema

Considera el siguiente fragmento de un documento en HTML:

1<ol id="o3">
2  <li class="c9">orangered</li>
3  <li class="c7">tomato</li>
4  <li class="c9 c7">firebrick</li>
5  <li id="choco">chocolate</li>
6  <ul>
7    <li class="c9">mintcream</li>
8  </ul>
9</ol>

Considera que al documento anterior se le están aplicando los siguientes estilos:

1*       {color: aqua;}
2@1      {color: firebrick;}
3#choco  {color: chocolate;}
4@2      {color: mintcream;}
5@3      {color: orangered;}
6@4      {color: tomato;}

Indica con qué sustituir las marcas @1, @2, @3 y @4 en el fragmento de CSS anterior para que cada elemento de la lista se muestre en el color que corresponde a su nombre, es decir, la palabra chocolate se muestre en color chocolate, etc. Asume que cualquier valor asignado a un atributo class puede estar asignado a otro atributo class en otras partes no mostradas del documento HTML y que cualquiera de los elementos HTML pueden estar siendo usados en otras partes del documento. Si hay más de una posibilidad para sustituir una determinada marca, pon la que menos caracteres ocupe.

Problema

Nota: este problema está basado en la rejilla de CSS, un tema que puede ser opcional en algunos cursos académicos; asegúrate de si este año lo es o no antes de intentar resolverlo.

Considera el siguiente fragmento de HTML:

1<div class="container">
2  <div class="cell">1</div>
3  <div class="cell">2</div>
4  <div class="cell">3</div>
5  <div class="cell">4</div>
6  <div class="cell menu">5</div>
7</div>

Y los siguientes estilos de CSS:

 1.container {
 2  display: grid;
 3  grid-template-columns: 1fr 1fr 1fr;
 4  grid-template-rows: repeat(@1, 2fr);
 5  grid-gap: 10px;
 6  text-align: center;
 7  background-color: #eee;
 8  border: 1px solid #000;
 9  color: #000;
10  width: 500px;
11  height: 250px;
12  --bg-color: #658db5;
13}
14
15.cell {
16  background-color: var(--bg-color);
17  padding: 25px;
18  border-radius: 6px;
19}
20
21.menu {
22  background-color: #898989;
23  grid-column: @2;
24  grid-row: @3 / 3;
25}

Indica con qué sustituir @1, @2 y @3 en el código anterior para que el documento se muestre como sigue:

Problema

Nota: este problema está basado en la rejilla de CSS, un tema que puede ser opcional en algunos cursos académicos; asegúrate de si este año lo es o no antes de intentar resolverlo.

Este problema incluye código que permite mostrar un sprite de 8x8 píxels usando rejillas de CSS. El código HTML es el siguiente:

 1<div class="duck">
 2  <!-- fila 1: -->
 3  <div class="i fondo"></div>
 4  <div class="i pato"></div>
 5  <div class="i pato"></div>
 6  <div class="i pato"></div>
 7  <div class="i pato"></div>
 8  <div class="i pato"></div>
 9  <div class="i pato"></div>
10  <div class="i pato"></div>
11  <!-- fila 2: -->
12  <div class="i fondo"></div>
13  <div class="i fondo"></div>
14  <div class="i pato"></div>
15  <div class="i pato"></div>
16  <div class="i pato"></div>
17  <div class="i pato"></div>
18  <div class="i pato"></div>
19  <div class="i pato"></div>
20  <!-- fila 3: -->
21  <div class="i fondo"></div>
22  <div class="i fondo"></div>
23  <div class="i pato"></div>
24  <div class="i pato"></div>
25  <div class="i pato"></div>
26  <div class="i pato"></div>
27  <div class="i pato"></div>
28  <div class="i pato"></div>
29  <!-- fila 4: -->
30  <div class="i fondo"></div>
31  <div class="i gafas"></div>
32  <div class="i gafas"></div>
33  <div class="i gafas"></div>
34  <div class="i gafas"></div>
35  <div class="i gafas"></div>
36  <div class="i gafas"></div>
37  <div class="i gafas"></div>
38  <!-- fila 5: -->
39  <div class="i fondo"></div>
40  <div class="i gafas"></div>
41  <div class="i gafas"></div>
42  <div class="i pato"></div>
43  <div class="i gafas"></div>
44  <div class="i gafas"></div>
45  <div class="i gafas"></div>
46  <div class="i pato"></div>
47  <!-- fila 6: -->
48  <div class="i pico"></div>
49  <div class="i pico"></div>
50  <div class="i pico"></div>
51  <div class="i pico"></div>
52  <div class="i pato"></div>
53  <div class="i pato"></div>
54  <div class="i pato"></div>
55  <div class="i pato"></div>
56  <!-- fila 7: -->
57  <div class="i fondo"></div>
58  <div class="i fondo"></div>
59  <div class="i pato"></div>
60  <div class="i pato"></div>
61  <div class="i pato"></div>
62  <div class="i pato"></div>
63  <div class="i pato"></div>
64  <div class="i pato"></div>
65  <!-- fila 8: -->
66  <div class="i fondo"></div>
67  <div class="i fondo"></div>
68  <div class="i pato"></div>
69  <div class="i pato"></div>
70  <div class="i pato"></div>
71  <div class="i pato"></div>
72  <div class="i pato"></div>
73  <div class="i pato"></div>
74</div>

Y los estilos de CSS son:

 1.duck {
 2  display: grid;
 3  grid-template-columns: repeat(@1, 10px);
 4  grid-template-rows: repeat(@2, 10px);
 5  grid-gap: 0;
 6  border: 1px solid black;
 7  width: 80px;
 8  height: 80px;
 9}
10
11.i {
12  width: @3;
13  height: @4;
14}
15
16.pato { background-color: white; }
17.pico { background-color: yellow; }
18.gafas { @5; }
19.fondo { background-color: gray; }

Indica con qué sustituir @1, @2, @3, @4 y @5 en el código anterior para que se muestre un sprite (tomado de [aquí](https://pixeljoint.com/pixelart/45130.htm)) de un pato con gafas de sol negras mirando a la izquierda como el siguiente:

Problema

Nota: este problema está basado en las animaciones de CSS, un tema que puede ser opcional en algunos cursos académicos; asegúrate de si este año lo es o no antes de intentar resolverlo.

Considera los siguientes estilos de CSS que permiten animar el carácter de la mano que saluda (en realidad, cualquier carácter) haciendo <span class="wave">👋🏾</span>. La idea es que la mano se pause durante la segunda mitad de la animación y que el movimiento se repita indefinidamente:

 1.wave {
 2  animation-name: wave-animation;
 3  animation-duration: 2.5s;
 4  animation-iteration-count: @1;
 5  transform-origin: 70% 70%;
 6  display: inline-block;
 7}
 8
 9@keyframes wave-animation {
10  0% { transform: rotate( 0.0deg) }
11  10% { transform: rotate(14.0deg) }
12  20% { transform: rotate(-8.0deg) }
13  30% { transform: rotate(14.0deg) }
14  40% { transform: rotate(-4.0deg) }
15  50% { transform: rotate(10.0deg) }
16  60% { transform: rotate(@2) }
17  100% { transform: rotate(0.0deg) }
18}

Indica con qué sustituir @1 y @2 para conseguir el efecto deseado. No es relevante para este problema, pero poner display a inline-block permite que la animación tenga realmente lugar porque estas no son posibles en elementos inline. Por otro lado, el valor de transform-origin se ha ajustado para que la mano rote desde la muñeca y no desde el punto central.

Problema

Considera el siguiente fragmento de un documento HTML:

<body>
  <div class="container">
    <div class="inner-box1">
      <div class="inner-box2"></div>
    </div>
  </div>
</body>

Considera también los siguientes estilos de CSS:

* {
  box-sizing: content-box;
  margin: 0;
  padding: 0;
}

.container {
  position: relative;
  width: 200px;
  height: 200px;
  background-color: #777;
}

.inner-box1 {
  position: @1;
  top: 50px;
  right: 50px;
  width: 100px;
  height: 100px;
  background-color: #aaa;
}

.inner-box2 {
  position: absolute;
  bottom: @2;
  left: @3;
  width: 50px;
  height: 50px;
  background-color: #ccc;
}

El código anterior corresponde a tres cuadrados anidados. El más grande tiene de lado 200 píxeles. El cuadrado mediano está centrado en el grande y su lado tiene la mitad de longitud del cuadrado grande. El tercer cuadrado está centrado en el cuadrado mediano y su lado tiene la mitad de longitud que este. Indica el código CSS por el que es necesario sustituir las marcas @1, @2 y @3 para que el fragmento HTML se muestre como sigue:

Considera que no hay otros estilos definidos que puedan entrar en conflicto con anteriores.

Problema

Queremos mostrar en el navegador fichas de libros que imitan las de cartulina que se usaban antaño en los ficheros de las bibliotecas:

El siguiente código en HTML y CSS permite mostrar una ficha como la anterior, pero la mayoría de los selectores han desaparecido de la hoja de estilo:

<!DOCTYPE html>
<html lang="es">
<head>
  <title>La Regenta I</title>
  <style>
    @import url('https://fonts.googleapis.com/css2?family=Seaweed+Script&display=swap');
    .card {
      background: floralwhite;
      box-shadow: 6px 6px 5px gray;
      width: 480px;
      height: 280px;
      padding: 5px;
    }
    @1 {
      width: 100%;
      background-color: steelblue;
      height: 2px;
    }
    @2 {
      font-family: 'Seaweed Script', cursive;
      font-size: 2em;
      bottom: 0;
      position: absolute;
      font-weight: bold;
    }
    @3 {
      width: 100%;
      background-color: red;
      height: 4px;
    }
    @4 {
      font-family: 'Seaweed Script', cursive;
      font-size: 1.2em;
      bottom: 0;
      position: absolute;
    }
    @5 {
      height: 60px;
      width: 100%;
      position: relative;
    }
    @6 {
      height: 30px;
      width: 100%;
      position: relative;
    }
  </style>
</head>
<body>
  <div class="card">
    <div class="card_title">
      <span class="text_title">La Regenta I</span>
    </div>
    <div class="redline"></div>
    <div class="card_row">
      <span class="text">
        <strong>Autor: </strong>Leopoldo Alas &laquo;Clarín&raquo;
      </span>
    </div>
    <div class="blueline"></div>
    <div class="card_row">
      <span class="text"><strong>Editorial: </strong>Cátedra</span>
    </div>
    <div class="blueline"></div>
    <div class="card_row">
      <span class="text"><strong>Año: </strong>2004</span>
    </div>
    <div class="blueline"></div>
    <div class="card_row">
      <span class="text"><strong>ISBN: </strong>978-84-376-0454-1</span>
    </div>
    <div class="blueline"></div>
    <div class="card_row"><span class="text"></span></div>
    <div class="blueline"></div>
    <div class="card_row"><span class="text"></span></div>
    <div class="blueline"></div>
  </div>
</body>
</html>

Observa el uso de posicionamientos absolutos en el código anterior para encajar correctamente las líneas de texto dentro de cada línea de la ficha. Por si no se aprecia, la línea más gruesa bajo «La Regenta I» es de color rojo y las demás son de color azul.

Indica con qué selectores se deberían sustituir las marcas desde @1 hasta @6 para que el resultado se muestre igual que en el ejemplo de ficha anterior.

Problema

Una librería de estilos de CSS establece una regla de la siguiente forma para todos los párrafos del documento:

body p {
  font-size: 1.2em;
  font-family: 'Times New Roman', serif;
  color: gray;
  text-align: justify;
}

Aunque no queremos dejar de usar la librería, deseamos que los párrafos de nuestro documento aparezcan en otro color y lo conseguimos añadiendo a este un estilo tan sencillo como el siguiente:

p {
  color: slategray @1;
}

Indica con qué sustituir la marca @1 para que los párrafos aparezcan en color slategray sin renunciar al resto de ventajas de la librería.

8.3. Programar el lado del cliente

Problema

¿Qué imprime el siguiente programa de JavaScript por la consola?

 1function outer(z) {
 2  var b = z;
 3  function inner() {
 4    var a = 20;
 5    console.log(a+b);
 6  }
 7  b+= 10;
 8  return inner;
 9}
10
11var X = outer(10);
12var Y = outer(20);
13X();
14Y();
15X();

Problema

Indica una expresión con la que sustituir la marca @1 en el siguiente código en JavaScript para que la siguiente función permita contar el número de veces que el carácter indicado como parámetro aparece dentro de la cadena sobre la que se invoca el método (por ejemplo, "foo".count('o') ha de devolver 2).

1String.prototype.count=function(c) {
2  var count=0, i=0;
3  while (i<this.length) {
4    count+= @1;
5  }
6  return count;
7};

Problema

Indica una única instrucción en JavaScript que use la siguiente declaración para imprimir un 100 por la consola.

1var logger= function () {
2  return function () {
3    return function () {
4      console.log(100);
5    }
6  }
7}

Problema

Indica con qué es necesario sustituir las marcas @1, @2 y @3 para que la siguiente función de JavaScript devuelva un valor booleano que indique si el array pasado como parámetro está ordenado de forma ascendente. Usa la notación @1=...,@2=...,@3=... para tu respuesta.

1function isSorted(array) {
2  const l = array.length - 1;
3  for (@1 i = 0; i < l; i++) {
4    const c = @2;
5    const n = @3;
6    if (c > n) { return false; }
7  }
8  return true;
9}

Problema

Indica con qué es necesario sustituir la marca @1 para que el siguiente código en JavaScript muestre por la consola el valor 42. Atención: el carácter de punto y coma no puede aparecer en tu respuesta para evitar que añadas instrucciones adicionales.

1(function(y) {
2  var answer = 40 + y;
3  console.log(answer);
4})@1;

Problema

¿Qué salida muestra por consola el siguiente programa en JavaScript?

 1function done(){
 2  console.log("Done");
 3}
 4
 5function increment(num, callBack){
 6  var f= callBack;
 7  for(var i = 0; i <= num; i++){
 8    console.log(i);
 9  }
10  return callBack();
11}
12
13increment(4, done);

Problema

Indica cuál es la salida por consola tras ejecutar el siguiente programa en JavaScript asumiendo que la función emit imprime por consola el valor pasado como parámetro tras realizar una serie de cálculos durante 1 segundo y que el tiempo de ejecución de cualquier otro elemento del código es despreciable.

 1function f(x) {
 2  emit("f"+(x||0));
 3}
 4
 5function g() {
 6  emit("g1");
 7  f(3);
 8  setTimeout(f,5000);
 9  emit("g2");
10}
11
12f(1);
13setTimeout(f,6000);
14g();
15f(2);

Para resolver este tipo de problemas te puede ayudar representar un cronograma similar al siguiente donde vayas registrando el código que se está ejecutando en cada momento, así como el código asíncrono que terminará encolando una función de callback:

cronograma

Problema

Considera el siguiente fragmento de un documento de HTML:

 1<body>
 2  <section>
 3    <header><h1>The Boy Who Lived</h1></header>
 4    <p class="first">Mr. and Mrs. Dursley, of number four,
 5      Privet Drive, were proud to say that they were perfectly
 6      normal, thank you very much.</p>
 7    <p class="last">They were the last people you'd expect to
 8      be involved in anything strange or mysterious, because they
 9      just didn't hold with such nonsense.</p>
10  </section>
11</body>

Considera que al documento anterior se le están aplicando los siguientes estilos:

 1p {
 2  color: silver;
 3}
 4#ch1 {
 5  color: tomato;
 6}
 7p.last {
 8  color: blueviolet;
 9}
10header h1 {
11  color: forestgreen;
12}
13p.first {
14  color: lightskyblue;
15}

Indica en qué colores se mostrarán, por este orden, el primer y segundo párrafo tras ejecutar el siguiente código de JavaScript:

1document.querySelector('p.last').parentNode.children[0].id= 'ch1';
2let e= document.querySelectorAll('p')[1];
3e.classList.toggle('first');
4e.previousSibling.previousSibling.classList.toggle('first');

Problema

Considera el siguiente fragmento en HTML de una página web:

 1<aside>
 2  <nav>
 3    <h1>Obras de Federico García Lorca</h1>
 4    <ol>
 5      <li>Poema del cante jondo</li>
 6      <li>Romancero gitano</li>
 7      <li>Poeta en Nueva York</li>
 8    <ol>
 9    <div>Sonetos del amor oscuro</div>
10    <ul>
11      <li>Bodas de sangre</li>
12    </ul>
13    <ul>
14      <li>La casa de Bernarda Alba</li>
15      <li>La zapatera prodigiosa</li>
16    </ul>
17  </nav>
18</aside>

Indica cuál es la salida por consola ejecutar el siguiente código en JavaScript:

1let l=document.querySelectorAll("aside > nav li");
2for (var i=0; i<l.length; i++) {
3  if (l[i].parentNode.querySelectorAll("li").length===1) {
4    console.log(l[i].textContent.length);
5  }
6}

Problema

¿Qué imprime el siguiente programa de JavaScript por la consola?

1function f(g,x) {
2  return {a:g,b:g(x)}
3}
4var h= f(x=>3*x,4);
5console.log(h.b-h.a(2));

Problema

Indica con qué sustituir las marcas @1 y @2 en el siguiente código en JavaScript para que la función every devuelva cierto si todos los elementos de un array cumplen una determinada condición pasada como parámetro y falso en otro caso.

1function every(array, predicate) {
2  for (var i=0;i<array.@1;i++) {
3    if (!@2) return false;
4  }
5  return true;
6}

Lo siguiente son un par de ejemplos de llamadas a la función; la primera devuelve cierto y la segunda devuelve falso:

1console.log(every([1, 3, 5], n => n < 10));
2console.log(every([2, 4, 16], n => n < 10));

Problema

Indique con qué sustituir @1, @2 y @3 en el siguiente código en JavaScript para que defina correctamente una clase Cilindro con un constructor y un método que calcula su volumen, además de crear un objeto de dicha clase e invocar sobre él la función volumen.

 1function Cilindro(a,d) {
 2  @1.altura = a;
 3  @1.diametro = d;
 4}
 5
 6Cilindro.@2.volumen = function () {
 7  var r = this.diametro / 2;
 8  return this.altura * Math.PI * r * r;
 9};
10
11var c = @3 Cilindro(7, 4);
12console.log(c.volumen().toFixed(4));  // imprime 87.9646

Problema

Indica cuál es la salida por consola tras ejecutar el siguiente programa en JavaScript, asumiendo que la función emit imprime por consola el valor pasado como parámetro tras realizar una serie de cálculos durante 1 segundo y que el tiempo de ejecución de cualquier otro elemento del código es despreciable. La función setTimeout es estándar de JavaScript y registra una función que se ejecutará asíncronamente después del número de milisegundos indicados como segundo parámetro.

 1function f(x) {
 2  if (x) {
 3    emit("f"+x);
 4  }
 5  else {
 6    setTimeout( ()=>emit("#") ,1000)
 7  }
 8}
 9
10function g() {
11  f();
12  setTimeout(f,1000);
13  emit("g1");
14  setTimeout(f,1000);
15  emit("g2");
16  for(var i=0;i<3;i++) {
17    emit("g3");
18  }
19
20}
21
22f(7);
23g();

Problema

Considera el siguiente fragmento de un documento en HTML:

1<ol id="c3">
2  <li class="a b">Gather ingredients</li>
3  <li class="b">Mix ingredients together</li>
4  <li class="a">Place ingredients in a baking dish</li>
5  <li>Bake in oven for an hour</li>
6  <li class="c">Remove from oven</li>
7  <li class="b" id="c1">Allow to stand for ten minutes</li>
8  <li id="c2">Serve</li>
9</ol>

Considera que al documento anterior se le están aplicando los siguientes estilos:

 1*     {color: aqua;}
 2li    {color: silver;}
 3li#c1 {color: darksalmon;}
 4li    {color: forestgreen;}
 5#c1   {color: lightskyblue;}
 6.a .b {color: orangered;}
 7ol li {color: firebrick;}
 8ol > li#c2 {color: lemonchiffon;}
 9li.a  {color: darkorchid;}
10li.b  {color: tomato;}
11li    {color: chocolate;}
12li#c3 {color: mintcream;}

Indica en el mismo orden la secuencia de los siete nombres de colores en los que se mostrarán los siete elementos de la lista de HTML tras ejecutar el siguiente código de JavaScript:

1let e=document.querySelectorAll('li');
2for(var i=0;i<e.length;i++) {
3  if (e[i].textContent.length===5) {
4    e[i].classList.add("a");
5  }
6}

Problema

Considera el siguiente fragmento del HTML de una página web:

 1<nav id="i100">
 2  <div class="a">
 3    <div>
 4      <span>Anduin</span>
 5      <span>Bruinen</span>
 6      <div>
 7        <span>Calenhir</span>
 8      </div>
 9      <span>Celduin</span>
10    </div>
11  </div>
12  <div lang="sjn">
13    <div>
14      <span>Celebrant</span>
15    </div>
16  </div>
17  <span>Bruinen</span>
18  <div lang="art">
19    <span>Anduin</span>
20    <span>Ciril</span>
21    <span>Entwash</span>
22    <span>Erui</span>
23    <span>Ethir<span>Bruinen</span></span>
24  </div>
25</nav>

Indica con qué sustituir la marca @1 en el siguiente código en JavaScript para que el primer elemento de tipo span que tiene como contenido la cadena Bruinen (hay tres en total) pase a tener un atributo spellcheck con valor false. Asume que cualquier valor asignado a un atributo class puede estar asignado a otro atributo class en otras partes no mostradas del documento HTML y que cualquiera de los elementos HTML pueden estar siendo usados en otras partes del documento. Si hay más de una posibilidad para sustituir una determinada marca, pon la que menos caracteres ocupe.

1var element= document.querySelector(@1);
2element.setAttribute("spellcheck",false);

Problema

Considera de nuevo todos los fragmentos de código del problema anterior. Indica con qué sustituir la marca @1 del código de JavaScript para que el segundo elemento de tipo span que tiene como contenido la cadena Bruinen (hay tres en total) pase a tener un atributo spellcheck con valor false. Asume que cualquier valor asignado a un atributo class puede estar asignado a otro atributo class en otras partes no mostradas del documento HTML y que cualquiera de los elementos HTML pueden estar siendo usados en otras partes del documento. Si hay más de una posibilidad para sustituir una determinada marca, pon la que menos caracteres ocupe.

Problema

Considera de nuevo todos los fragmentos de código del problema anterior. Indica con qué sustituir la marca @1 del código de JavaScript para que el tercer elemento de tipo span que tiene como contenido la cadena Bruinen (hay tres en total) pasen a tener un atributo spellcheck con valor false. Asume que cualquier valor asignado a un atributo class puede estar asignado a otro atributo class en otras partes no mostradas del documento HTML y que cualquiera de los elementos HTML pueden estar siendo usados en otras partes del documento. Si hay más de una posibilidad para sustituir una determinada marca, pon la que menos caracteres ocupe.

Problema

Indica con qué sustituir las marcas @1, @2, @3, @4 en el siguiente programa de JavaScript para que la salida sea 7.

1let c= {gamma:2};
2let h1= x =@1 x*x;
3let h2= (x,y) =@2 h1(x)*c.@3-h1(y);
4console.log(h2(4,@4));

Problema

En el siguiente programa en JavaScript la función emit imprime por consola el valor pasado como parámetro tras realizar una serie de cálculos durante 1 segundo. El tiempo de ejecución de cualquier otro elemento del código es despreciable. La función setTimeout es estándar de JavaScript y registra una función que se ejecutará asíncronamente después del número de milisegundos indicados como segundo parámetro. Indica con qué sustituir la marca @1 para que se impriman por consola en este orden los valores 1, 2, 3, 4, 5, 6, 7, 8.

 1let lista=@1
 2
 3for(let i=0;i<lista.length;i++) {
 4  if (i==2 || i==3) {
 5    setTimeout(function() {emit(lista[i])}, 2000);
 6  }
 7  else if (i==4 || i==5) {
 8    setTimeout(function() {emit(lista[i])}, 1000);
 9  }
10  else {
11    emit(lista[i]);
12  }
13}

Observa que la variable lista es un array de números que serán impresos dentro del bucle, por lo que una posible respuesta (incorrecta) sería @1=[8,7,6,5,4,3,2,1].

Problema

Indica con qué sustituir @1, @2, @3 y @4 en el siguiente código en JavaScript para que se creen en memoria los objetos indicados en el diagrama y se muestre por la consola la cadena Esta persona se llama Jane.

 1class Person {
 2  @1() {
 3    return 'Esta persona se llama '+this.name;
 4  }
 5  @2(name) {
 6    @3 = name;
 7  }
 8}
 9const jane = @4 Person('Jane');
10console.log(jane.describe());
objetos de JavaScript en memoria

Objetos de JavaScript en memoria por Axel Rauschmayer

Problema

Indica cuál es la salida del siguiente código en JavaScript:

 1function creaBichoBola(proto,exoesqueleto) {
 2  let bicho= Object.create(proto);
 3  bicho.exoesqueleto= exoesqueleto;
 4  return bicho;
 5};
 6protoBichoBola = {
 7  enrolla: function() {console.log("grrrr")},
 8  desplaza: function() {console.log("shhhh")}
 9};
10function Bolinche() {
11  this.x= -1;
12}
13Bolinche.prototype= protoBichoBola;
14var bicho = new Bolinche();
15var bicho2= creaBichoBola(protoBichoBola);
16console.log(bicho.prototype === bicho2.prototype);
17console.log(Object.getPrototypeOf(bicho) === Object.getPrototypeOf(bicho2));
18console.log(Object.getPrototypeOf(protoBichoBola) === Object.prototype);
19console.log(protoBichoBola.enrolla.prototype === protoBichoBola.desplaza.prototype);

Problema

Indica con qué hay que sustituir @1 y @2 en el siguiente código para que la salida emitida sea 30 42.

 1function f1(n) {
 2  var a= @1;
 3  function f2(i) {
 4    let k= n*a*i;
 5    console.log(k);
 6  }
 7  f2(@2);
 8  a= 7;
 9  return f2;
10}
11
12var f = f1(3);
13f(@2);

Problema

Considera un documento HTML cuyo cuerpo (contenido del elemento body) es el siguiente:

1<div class="cuadrados">
2  <div class="orange">naranja</div>
3  <div class="blue">azul</div>
4  <div class="lavender">lavanda</div>
5</div>

y al cual se les están aplicando los siguientes estilos:

 1* {
 2    box-sizing: border-box;
 3    margin: 0;
 4    padding: 0;
 5}
 6.cuadrados {
 7    width: 400px;
 8    height: 400px;
 9    background: gainsboro;
10    padding-left: 50px;
11    padding-top: 50px;
12    position: relative;
13}
14.orange {
15    background: orange;
16    height: 100px;
17    width: 100px;
18    position: relative;
19    z-index: @1;
20}
21.blue {
22    background: lightskyblue;
23    height: 100px;
24    width: 100px;
25    position: absolute;
26    left: 210px;
27    top: 50px;
28}
29.lavender {
30    background: lavender;
31    height: 100px;
32    width: 100px;
33    position: relative;
34}

El siguiente código en JavaScript tiene como objetivo mover horizontalmente el cuadrado naranja a una velocidad de 1 píxel cada 10 milisegundos desde su posición inicial hasta situarlo encima del cuadrado azul. La función setTimeout es estándar de JavaScript y registra una función que se ejecutará asíncronamente después del número de milisegundos indicados como segundo parámetro.

 1let a= document.querySelector(".orange");
 2let i= 0;
 3
 4function mueve() {
 5    i++;
 6    a.style.left= i+@2;
 7    if (i<@3) {
 8    setTimeout(mueve,10);
 9    }
10}
11
12setTimeout(mueve,10);

Indica con qué sustituir @1 en la hoja de estilo y @2 y @3 en el código de JavaScript anterior para que se consiga el efecto deseado.

Problema

En el siguiente programa en JavaScript la función emit imprime por consola el valor pasado como parámetro tras realizar una serie de cálculos durante 1 segundo. El tiempo de ejecución de cualquier otro elemento del código es despreciable. La función setTimeout es estándar de JavaScript y registra una función que se ejecutará asíncronamente después del número de milisegundos indicados como segundo parámetro. Indica con qué sustituir la marca @1 para que se impriman por consola en este orden los valores 0, 1, 2, 3, 3, 2, 2, 1, 1, 0.

 1let lista=@1;
 2
 3function foo(j) {
 4    emit(j);
 5    emit(j);
 6}
 7
 8for(let i=0;i<lista.length;i++) {
 9    console.log(i);
10    if (i > 1) {
11    setTimeout(() => foo(lista[i]),2000);
12    }
13    else {
14    setTimeout(() => emit(lista[i]), 3000-1000*i);
15    }
16}

Observa que la variable lista es un array de números que serán impresos dentro del bucle, por lo que una posible respuesta (incorrecta) sería @1=[1,5,1,5,1,5].

Problema

Una vez completo, el siguiente programa en JavaScript crea dos objetos, t1 y t2, con atributos que representan las longitudes de los tres lados de un triángulo y les asocia un prototipo que incluye una función que permite obtener el perímetro (es decir, la suma de las longitudes de sus lados: 9 para el primer triángulo y 6 para el segundo).

1var t1={};
2t1.a=t1.b=t1.c=3;
3var x={getPerimeter: function () {return @1;}};
4Object.@2(t1,x);
5console.log(t1.getPerimeter());
6var t2=Object.@3;
7t2.a=t2.b=t2.c=2;
8console.log(t2.getPerimeter());

Indica con qué sustituir @1, @2 y @3 en el programa anterior para que el código funcione de la forma indicada e imprima los valores 9 y 6.

Problema

Considera el siguiente fragmento HTML de una página web que representa un tablero del juego del tres en raya con piezas de ambos jugadores (representadas mediante el prefijo X u O, según el jugador):

 1<table id="tictactoe">
 2    <tr>
 3    <td class="X">X1</td><td class="X">X2</td><td class="X">X3</td>
 4    </tr>
 5    <tr>
 6    <td></td><td class="O">O2</td><td></td>
 7    </tr>
 8    <tr>
 9    <td class="O">O1</td><td></td><td></td>
10    </tr>
11</table>

Considera los siguientes estilos CSS asociados a la página anterior:

 1* {
 2    padding: 0;
 3    margin: 0;
 4}
 5
 6table {
 7    border-spacing: 2px;
 8}
 9
10td {
11    width: 30px;
12    height: 30px;
13    border: 1px solid black;
14    padding: 5px;
15    text-align: center;
16}
17
18.O {
19    color: seagreen;
20}
21
22.X {
23    color: darkslateblue;
24}
25
26.pieza {
27    background-color: lightgray;
28}
29
30.izquierda {
31    border-left: 3px solid gray;
32}
33
34.derecha {
35    border-right: 3px solid darkgray;
36}
37
38.arriba {
39    border-top: 3px solid silver;
40}
41
42.abajo {
43    border-bottom: 3px solid dimgray;
44}

Indica con qué sustituir @1, @2, @3 y @4 en el siguiente código de JavaScript para que todas las celdas de la tabla en las que hay una pieza de tipo X se muestren con fondo de color lightgray:

1var a= document.querySelector("#tictactoe");
2var b= a.querySelectorAll("td");
3for (var e of b) {
4    if (e.@1!=="" && e.@2==="X") {
5    e.@3.add(@4);
6    }
7}

Problema

Dado el código HTML y CSS del ejercicio del tres en raya anterior, indica con qué sustituir @1 y @2 en el siguiente código en JavaScript para que se muestra una especie de borde alrededor del tablero. Este efecto se obtiene marcando el borde externo de las celdas con distinto color según la posición de cada una (silver para las celdas de la primera fila, dimgray para las de la última fila, gray para las de la primera columna y darkgray para las de la última columna).

 1var a= document.querySelector("#tictactoe");
 2var b= a.querySelectorAll("td:nth-child(1)");
 3for (var e of b) {
 4    e.classList.add("izquierda");
 5}
 6b= a.querySelectorAll("td:last-child");
 7for (var e of b) {
 8    e.classList.add("derecha");
 9}
10b= a.querySelectorAll(@1);
11for (var e of b) {
12    e.classList.add("arriba");
13}
14b= a.querySelectorAll(@2);
15for (var e of b) {
16    e.classList.add("abajo");
17}

Problema

Indica con qué sustituir @1 y @2 en el siguiente bloque de código para que por la salida se muestren los números 2, 2, 0 y 1 (en este orden):

1@1 i=0;
2var j=0;
3while (i<2) {
4    i++;
5    @2 k= j++;
6    setTimeout(() => {console.log(i)}, 100);
7    setTimeout(() => {console.log(k)}, 500);
8}

Problema

Indica con qué sustituir @1 y @2 en el siguiente bloque de código JavaScript para que compact sea una función que devuelva una copia del array recibido como parámetro en la que se han eliminado todos los valores que en JavaScript se consideran falsos cuando son interpretados como un booleano.

 1function compact(arr1) {
 2    arr2= @1;
 3    for (var i=0;i<arr1.length;i++) {
 4    if (@2) {
 5        arr2.push(arr1[i]);
 6    }
 7    }
 8    return arr2;
 9}
10
11a= [0,false,undefined,5,"",6,null];
12console.log(compact(a));  // imprime [5,6]

Problema

Considera un documento HTML cuyo cuerpo (contenido del elemento body) es el siguiente:

1<div class="cuadrados"></div>

y al cual se les están aplicando los siguientes estilos:

 1* {
 2    box-sizing: border-box;
 3    margin: 0;
 4    padding: 0;
 5}
 6.cuadrados {
 7    width: 400px;
 8    height: 400px;
 9    background: gainsboro;
10    padding-left: 50px;
11    padding-top: 50px;
12    position: relative;
13}
14.bloque {
15    height: 100px;
16    width: 100px;
17    position: absolute;
18}

Considera ahora el siguiente código incompleto en JavaScript:

 1let colores=[@1,"lavender"]
 2let arena= document.querySelector(".cuadrados");
 3
 4for (let i=1;i<=11;i++) {
 5    var n= document.createElement("div");
 6    n.classList.add("bloque");
 7    var color= colores[i%colores.length];
 8    n.style.background= color;
 9    n.style.left= 0+25*i+"px";
10    n.style.top= @2;
11    n.textContent= @3;
12    arena.appendChild(n);
13}

Indica con qué sustituir @1, @2 y @3 en el código de JavaScript anterior para que se muestre en el navegador un documento como el de la imagen siguiente:

cuadrados

Problema

Dado el mismo código en HTML, CSS y JavaScript del problema anterior, se pretende conseguir que el navegador muestre ahora un documento como el siguiente:

cuadrados

Para ello, se hace sobre el código en JavaScript completo (es decir, el código correcto sin los huecos de las arrobas del problema anterior) un único cambio: añadir a continuación de la línea que asigna valor a la variable color la línea:

1n.style.zIndex= @1 i;

Indica con qué parte de una subexpresión hay que sustituir @1 en la línea anterior para conseguir que el navegador muestre el documento como en la captura de este problema.

Notas: observa que el número de cuadrados mostrados es menor que en el problema anterior, pero las condiciones del bucle no han cambiado. Recuerda que en JavaScript para cambiar una propiedad de CSS como margin-bottom es necesario modificar elemento.style.marginBottom y no elemento.style.margin-bottom, ya que esto se interpretaría como la resta del valor de dos variables. Ten en cuenta que no es necesario haber resuelto correctamente el problema anterior para poder responder a este correctamente.

Problema

Cuando en JavaScript se utiliza el operador de comparación no estricta ==, el intérprete realiza una serie de conversiones de tipo entre los operandos afectados. Para simplificar, asumamos, por ejemplo, que si se está comparando un objeto con un dato de un tipo simple como una cadena o un entero, se llama a la función toString del objeto antes de realizar la comparación. Esto permite escribir una instrucción condicional como la del siguiente código que se evalúe a cierto, aunque en un principio la condición nos pueda parecer falsa.

 1let a = {
 2    i: 1,
 3    toString: function () {
 4    return "" + @1;
 5    }
 6}
 7
 8if(a == "1" && a == "2" && a == 3) {
 9    console.log('Hello world!');
10}

Indica con qué sustituir @1 en el código anterior para que se imprima Hello world! por la consola. Nota: el operador && se evalúa de izquierda a derecha.

Problema

Considera esta lista de reglas de CSS:

  1. aside + p {color:red}

  2. #a #b {color:red}

  3. section > p {color:red}

Considera también estos fragmentos de código en HTML:

  1. <section id="a"><aside><p>rainbow</p></aside><p>cat</p></section>

  2. <section id="a"><aside class="b"><p>rainbow</p></aside><span>super</span><p>cat</p></section>

  3. <section id="a"><aside><p>rainbow</p></aside><p>super</p><p id="b">cat</p></section>

Asocia cada regla con un código HTML diferente de manera que solo la palabra cat aparezca en rojo y las demás no. Usa una notación como 1-1 para indicar que la regla 1 se asocia con el código de la línea marcada con 1 (nota: este ejemplo de asociación no es necesariamente parte de la respuesta correcta).

Problema

Indica cuál es la salida por consola del siguiente bloque de JavaScript. Asume que todas las instrucciones tienen un tiempo de ejecución despreciable pero no nulo.

 1var i=1;
 2var j=0;
 3while (j<2) {
 4    i++;
 5    let x= i;
 6    let y= j;
 7    var z= j++;
 8    setTimeout(() => {console.log(x)}, 10);
 9    setTimeout(() => {console.log(y)}, 100);
10    setTimeout(() => {console.log(z)}, 1000);
11}

Problema

Sabiendo que en el caso de que se indique cero como segundo argumento de la función setTimeout de JavaScript, la llamada a la función del primer argumento se encola inmediatamente, indica cuál es la salida por consola del siguiente bloque de JavaScript.

 1(function() {
 2    console.log('r');
 3    setTimeout( () => {console.log('a')}, 0);
 4    (function() {
 5    console.log('o');
 6    setTimeout( () => {console.log('p')}, 0);
 7    console.log('c');
 8    setTimeout( () => {console.log('t')}, 0);
 9    console.log('i');
10    })();
11    console.log('n');
12    setTimeout( () => {console.log('o')}, 0);
13})();

Problema

El método Array.prototype.map() crea un nuevo array con los resultados de la llamada a la función indicada aplicados a cada uno de los elementos del array original. Así, el siguiente código imprime por consola [ 1, 4, 9, 16, 25 ]:

1arr= [1,2,3,4,5]
2const newArr = arr.map((val) => val * val);
3console.log(newArr);

Considera ahora el siguiente código en JavaScript:

 1const animals = [
 2    { name: 'shark', likes: 'ocean' },
 3    { name: 'turtle', likes: 'pond' },
 4    { name: 'otter', likes: 'fish biscuits' },
 5    { name: 'ico', likes: ''}
 6]
 7
 8const likes = animals.map(item => {
 9    const container = @1;
10    container@2 = item.likes;
11    container.sup = item.name.@3 * 10;
12    return container;
13})
14
15console.log(likes);

Indica con qué sustituir @1, @2 y @3 en el código anterior para que la salida por consola sea:

1[{"shark":"ocean","sup":50},{"turtle":"pond","sup":60},{"otter":"fish biscuits","sup":50},{"ico":"","sup":30}]

Problema

Considera el siguiente código en HTML:

1<ul class="set">
2    <li class="white do"></li> <li class="black dos"></li>
3    <li class="white re"></li> <li class="black res"></li>
4    <li class="white mi"></li>
5    <li class="white fa"></li> <li class="black fas"></li>
6    <li class="white sol"></li> <li class="black sols"></li>
7    <li class="white la"></li> <li class="black las"></li>
8    <li class="white si"></li>
9</ul>

Y el siguiente código en CSS (basado en el creado por Philip Zastrow en codepen.io) al que le faltan algunos fragmentos:

 1* {
 2    box-sizing:border-box
 3}
 4
 5body {
 6    margin:0;
 7    background:#222
 8}
 9
10ul {
11    height:20em;
12    width:34em;
13    margin:5em auto;
14    padding:3em 0 0 3em;
15    position:relative;
16    background-color: gray;
17}
18
19li {
20    margin:0;
21    padding:0;
22    list-style:none;
23    position:relative;
24    float: left;
25}
26
27ul .white {
28    height:16em;
29    width: @1;
30    z-index:1;
31    border-left:1px solid #bbb;
32    border-bottom:1px solid #bbb;
33    border-radius:0 0 5px 5px;
34    background-color: white;
35}
36
37.black {
38    height:8em;
39    width:2em;
40    margin:0 0 0 -1em;
41    z-index: @2;
42    border:1px solid #000;
43    border-radius:0 0 3px 3px;
44    background-color: black;
45}
46
47.re,.mi,.sol,.la,.si {
48    margin:0 0 0 @3
49}
50
51ul li:first-child {
52    border-radius:5px 0 5px 5px
53}
54
55ul li:last-child {
56    border-radius:0 5px 5px 5px
57}

El código anterior muestra en la ventana del navegador el siguiente piano:

piano horizontal

La propiedad float:left de CSS que se usa en el ejemplo anterior hace que la caja de cada elemento li no se posicione debajo de la anterior (como correspondería por defecto), sino que se desplace a la izquierda hasta tocar el borde de la caja contenedora o el borde de otro elemento flotante. Esto es lo que permite que cada tecla aparezca a la derecha de la anterior y no debajo, aunque, como puedes ver en el código, hace falta un pequeño reajuste para colocarlas correctamente, ya que las teclas negras de los semitonos se sitúan a medio camino entre las blancas. Aunque no es muy relevante para este problema, la propiedad border-radius define la curvatura de las esquinas comenzando por la superior izquierda. Finalmente, puedes ignorar el uso del posicionamiento relativo en este código.

Indica con qué sustituir @1, @2 y @3 en el código en CSS anterior para que el piano se muestre como en la imagen.

Problema

Indica qué nueva regla añadir a la hoja de estilo del problema anterior para que la tecla del re se muestre en color rojo como en la siguiente imagen.

piano horizontal con tecla roja

Problema

Indica cuál es la salida por consola tras ejecutar el siguiente programa en JavaScript:

 1function A (x) {
 2    this.x= x;
 3}
 4let c= console.log;
 5let a1= new A(9);
 6A.prototype.f= function () {
 7    c(this.x);
 8};
 9a1.f();
10a1.f= () => c(0);
11let a2= new A(8);
12a1.f();
13a2.f();
14Object.getPrototypeOf(a1).f= () => c(1);
15a1.f();
16a2.f();

Problema

El método Array.prototype.reduce() ejecuta una función reductora sobre cada elemento del array y devuelve finalmente un único valor. La función reduce tiene el siguiente prototipo:

1arr.reduce(callback(acumulador, valorActual), valorInicial)

La función callback(acumulador,valorActual) tiene dos parámetros cuyo papel es el siguiente:

  • acumulador: es el valor acumulado devuelto en la anterior invocación de callback; en la primera llamada se inicializa al valor del parámetro valorInicial.

  • valorActual: el elemento del array que está siendo procesado actualmente.

Así, el siguiente código imprime por consola el valor 6:

1console.log([0, 1, 2, 3].reduce(function(a, b) {return a + b;}));

Por otra parte, el método Array.prototype.concat() devuelve un nuevo array que es el resultado de concatenar los elementos de dos arrays: el array del objeto receptor del mensaje y el recibido como parámetro.

Considera ahora el siguiente código en JavaScript que permite integrar un array de arrays:

1var arr = [[0,1], [2,3], [4,5]];
2var integrado = arr.@1( (a,b) => @2.@3(@4), [] );
3console.log(integrado);

Indica con qué sustituir @1, @2, @3 y @4 en el código anterior para que la salida por consola sea:

1[4, 5, 2, 3, 0, 1]

Problema

Considera el siguiente código en HTML:

1<ul class="set">
2    <li class="white do"></li> <li class="black dos"></li>
3    <li class="white re"></li> <li class="black res"></li>
4    <li class="white mi"></li>
5    <li class="white fa"></li> <li class="black fas"></li>
6    <li class="white sol"></li> <li class="black sols"></li>
7    <li class="white la"></li> <li class="black las"></li>
8    <li class="white si"></li>
9</ul>

Y el siguiente código en CSS al que le faltan algunos fragmentos:

 1* {
 2    box-sizing: border-box;
 3}
 4
 5body {
 6    margin: 0;
 7    background: #222;
 8}
 9
10ul {
11    height: 34em;
12    width: 22em;
13    margin: 5em auto;
14    padding: 3em 0 0 3em;
15    background-color: gray;
16}
17
18li {
19    margin: 0;
20    padding: 0;
21    list-style: none;
22    position: relative;
23}
24
25ul .white {
26    height: 4em;
27    width: 16em;
28    z-index: 1;
29    border-left: 1px solid #bbb;
30    border-bottom: 1px solid #bbb;
31    background-color: white;
32}
33
34.black {
35    height: 2em;
36    width: @1;
37    margin: -1em 0 0 @2;
38    z-index: 2;
39    border: 1px solid #000;
40    background-color: black;
41}
42
43.re,.mi,.sol,.la,.si {
44    margin: @3 0 0 0;
45}

El código anterior muestra en la ventana del navegador el siguiente piano donde la tecla del do es la de más arriba:

piano vertical

Como puedes ver en el código, hace falta un pequeño reajuste jugando con los márgenes para colocar correctamente las teclas; por ejemplo, en el caso de las teclas negras de los semitonos, estas se sitúan a medio camino entre las blancas. Por otro lado, puedes ignorar el uso del posicionamiento relativo en este código.

Indica con qué sustituir @1, @2 y @3 en el código en CSS anterior para que el piano se muestre como en la imagen.

Problema

Dado el mismo código HTML del problema anterior, las siguientes reglas de estilo permiten obtener la misma imagen, pero en esta ocasión usando las propiedades de posicionamiento de CSS:

  1* {
  2    box-sizing:border-box;
  3}
  4
  5body {
  6    margin: 0;
  7    background: #222;
  8}
  9
 10ul {
 11    height: 34em;
 12    width: 22em;
 13    margin: 5em auto;
 14    padding: 3em 0 0 3em;
 15    position: relative;
 16    background-color: gray;
 17}
 18
 19li {
 20    margin: 0;
 21    padding :0;
 22    list-style: none;
 23}
 24
 25ul .white {
 26    height: 4em;
 27    width: 16em;
 28    z-index: 1;
 29    border: 1px solid #bbb;
 30    background-color: white;
 31}
 32
 33.black {
 34    height: 2em;
 35    width: 8em;
 36    margin-left: @1;
 37    z-index: 2;
 38    border: 1px solid #000;
 39    background-color: black;
 40}
 41
 42.do {
 43    position: absolute;
 44    top: 3em;
 45}
 46
 47.re {
 48    position: absolute;
 49    top: 7em;
 50}
 51
 52.mi {
 53    position: absolute;
 54    top: 11em;
 55}
 56
 57.fa {
 58    position: absolute;
 59    top: 15em;
 60}
 61
 62.sol {
 63    position: absolute;
 64    top: 19em;
 65}
 66
 67.la {
 68    position: absolute;
 69    top: 23em;
 70}
 71
 72.si {
 73    position: absolute;
 74    top: 27em;
 75}
 76
 77.dos {
 78    position: absolute;
 79    top: 6em;
 80}
 81
 82.res {
 83    position: absolute;
 84    top: @2;
 85}
 86
 87.fas {
 88    position: absolute;
 89    top: @3;
 90}
 91
 92.sols {
 93    position: absolute;
 94    top: @4;
 95}
 96
 97.las {
 98    position: absolute;
 99    top: 26em;
100}

Indica con qué sustituir @1, @2, @3 y @4 en el código anterior para obtener la misma imagen que en el problema anterior.

Problema

Dibuja aproximadamente cómo se mostraría en un navegador el siguiente fragmento HTML si se usaran (una vez completas) las reglas de estilo del problema anterior:

 1<ul class="set">
 2    <li class="white do"></li>
 3    <li class="white re"></li>
 4    <li class="white mi"></li>
 5    <li class="white fa"></li>
 6    <li class="white sol"></li>
 7    <li class="white la"></li>
 8    <li class="white si"></li>
 9    <li class="black res"></li>
10    <li class="black dos"></li>
11    <li class="black fas"></li>
12    <li class="black sols"></li>
13    <li class="black las"></li>
14</ul>

Problema

En CSS, las propiedades personalizadas (también conocidas como variables) son propiedades especiales que contienen valores específicos que se pueden volver a utilizar en un documento por medio de la función var() e incluso operar mediante la función calc(). Uno de sus usos más habituales es el de evitar tener que indicar el mismo valor literal en múltiples partes de un documento CSS. Como muchas otras propiedades de CSS, las variables en un nodo heredan el valor del nodo padre. Como ejemplo de todo esto, el siguiente bloque de HTML muestra una serie de botones de colores diferentes similares a los que se pueden obtener con Bootstrap:

1<section>
2    <button class="btn primary">Primary</button>
3    <button class="btn secondary">Secondary</button>
4    <button class="btn error">Error</button>
5</section>

Para ello, usa los siguientes estilos, donde puedes ver cómo se definen diferentes variables:

 1* {
 2    border: 0;
 3}
 4html {
 5    --primary: #0076c6;
 6    --secondary: #333333;
 7    --white: #ffffff;
 8    --error: #ee0000
 9}
10.btn {
11    padding: 1rem 1.5rem;
12    background: transparent;
13    font-weight: 700;
14    border-radius: 0.5rem;
15    cursor: pointer;
16    outline: none;
17}
18.primary {
19    background: var(--primary);
20    color: var(--white);
21}
22.secondary {
23    background: var(--secondary);
24    color: var(--white);
25}
26.error {
27    background: var(--error);
28    color: var(--white);
29}

Ahora considera un documento HTML con el siguiente contenido:

1<div class="mover"></div>

Considera también el siguiente código de CSS aplicado al documento anterior:

1.mover {
2    width: 50px;
3    height: 50px;
4    background: red;
5    position: absolute;
6    left: calc( var(--mouse-x) + 10px );
7    top: var(--mouse-y);
8}

Finalmente, asume que se ha definido el siguiente manejador de evento que se invoca por el navegador cada vez que la persona usuaria mueve el ratón (las coordenadas actuales del ratón se asignan a los atributos clientX y clientY del argumento):

1let root = document.querySelector("html");
2
3root.addEventListener("mousemove", e => {
4    root.style.setProperty('--mouse-x', e.clientX + "px");
5    root.style.setProperty('--mouse-y', e.clientY + "px");
6});

Indica en qué coordenadas (x,y) se encuentra el píxel de la esquina inferior derecha del cuadrado rojo cuando el puntero del ratón está en las coordenadas (40,50).

Problema

Considera el siguiente código JavaScript que define un componente web que muestra una barra verde sobre fondo gris que indica el porcentaje de progreso de una tarea:

class ProgressBar extends HTMLElement {
  constructor() {
    super();
    this._shadowRoot = this.attachShadow({ mode: 'open' });
    this._shadowRoot.innerHTML = `
      <style>
        #container {
          width: 300px;
          height: 20px;
          background-color: #ddd;
          border-radius: 10px;
        }
        #bar {
          height: 100%;
          background-color: #0a0;
          width: 0;
          border-radius: 10px;
        }
      </style>
      <div id="container">
        <div id="bar"></div>
      </div>
    `;
    this.$bar = @1.querySelector('#bar');
  }

  static get observedAttributes() {
    return [@2];
  }

  attributeChangedCallback(name, oldValue, newValue) {
    if (name === 'value') {
      @3.style.@4 = `${newValue}%`;
    }
  }

}

customElements.define('progress-bar', ProgressBar);

Para usar este componente, basta escribir el siguiente código HTML, que será complementado normalmente con código en JavaScript que vaya actualizando el valor del atributo value:

<progress-bar value="65"></progress-bar>

Sustituye @1, @2, 3 y @4 por el código JavaScript necesario para que el componente web se comporte correctamente.

Problema

En el siguiente programa en JavaScript la función emit imprime por consola el valor pasado como parámetro tras realizar una serie de cálculos durante 1 segundo. El tiempo de ejecución de cualquier otro elemento del código es no nulo pero virtualmente infinitesimal. La función setTimeout es estándar de JavaScript y registra una función que se ejecutará asíncronamente después del número de milisegundos indicados como segundo parámetro. Indica con qué sustituir la marca @1 para que se impriman por consola en este orden los valores 2, 3, 1, 0, 2, 3.

let lista=@1

for(let i=0;i<lista.length;i++) {
  if (lista[i]==1 || lista[i]==0) {
    setTimeout(function() {emit(lista[i])}, 2000);
    setTimeout(function() {emit(lista[i+1])}, 5000);
  }
  else {
    emit(lista[i]);
  }
}

Observa que la variable lista es un array de números que serán impresos dentro del bucle, por lo que una posible respuesta (incorrecta) sería @1=[2,3,1,0,2,3].

Problema

Considera este código de JavaScript:

const AnimalPrototype = {
  count: 0,  // atributo estático
  makeSound: function() {
    console.log(`el ${this.name} (${this.id}/${AnimalPrototype.@1}) hace ${this.sound}`);
  }
};

function Animal(name, sound) {
  this.name = name;
  this.sound = sound;
  this.id = ++Animal.prototype.count;
}

Animal.@2 = @3;

const animal1 = Object.@4(AnimalPrototype);
animal1.name = 'gato';
animal1.sound = 'miau';
animal1.id = ++Animal.prototype.count;

const animal2 = @5 Animal('gallo', 'kikiriki');

console.log(`total: ${Animal.prototype.count}`);
animal1.makeSound();
animal2.makeSound();

El código anterior crea dos objetos en JavaScript e imprime lo siguiente en consola:

total: 2
el gato (1/2) hace miau
el gallo (2/2) hace kikiriki

Indica el valor de las marcas @1, @2, @3, @4 y @5 para que el código anterior funcione como se ha indicado.

Problema

La sencilla aplicación web que se estudia en este problema muestra una cuenta atrás hasta la entrada del año 2024. Unos segundos después de alcanzado ese momento, el contador desaparece y se muestra un mensaje de felicitación con emojis. El fichero index.html es el siguiente:

<html>
  <head>
    <title>Countdown to a new year</title>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <script src="script.js"></script>
    <div class="container">
      <h1 id="headline">Countdown to a new year</h1>
      <div id="countdown">
        <ul>
          <li><span id="days"></span>days</li>
          <li><span id="hours"></span>Hours</li>
          <li><span id="minutes"></span>Minutes</li>
          <li><span id="seconds"></span>Seconds</li>
        </ul>
      </div>
      <div id="content" class="emoji">
        <span>🥳</span>
        <span>🎉</span>
        <span>🎂</span>
      </div>
    </div>
  </body>
</html>

El fichero style.css es el siguiente:

 * {
   box-sizing: border-box;
   margin: 0;
   padding: 0;
 }

 body {
   background-color: #ffd54f;
   font-family: Roboto, Ubuntu, sans-serif;
 }

 .container {
   color: #333;
   margin: 0 auto;
   text-align: center;
 }

 h1 {
   font-weight: normal;
   letter-spacing: .125em;
   text-transform: uppercase;
 }

 li {
   display: inline-block;
   font-size: 1.5em;
   list-style-type: none;
   padding: 1em;
   text-transform: uppercase;
 }

 li span {
   display: block;
   font-size: 4.5em;
 }

 .emoji {
   display: @1;
   padding: 1em;
 }

Finalmente, el fichero script.js es el siguiente:

(function () {
  const second = 1000;
  const minute = second * 60;
  const hour = minute * 60;
  const day = hour * 24;

  newyear =  "Jan 1, 2024 00:00:30";

  const countDown = new Date(newyear).getTime();
  const x = setInterval(function() {

        const now = new Date().getTime();
        const distance = countDown - now;  // milliseconds until new year

        document.getElementById("days").innerText =
                Math.floor(distance / (day));
        document.getElementById("hours").innerText =
                Math.floor((distance % (day)) / (hour));
        document.getElementById("minutes").innerText =
                Math.floor((distance % (hour)) / (minute));
        document.getElementById("seconds").innerText =
                Math.floor((distance % (minute)) / second);

        // do something when date is reached
        if (distance < 0) {
          document.getElementById("headline").innerText = "Happy New Year!";
          document.getElementById(@2).style.display = "none";
          document.getElementById("content").style.display = @3;
          clearInterval(x);
        }
        //seconds
      }, 1000)
  }());

La función setInterval define una función que se ejecuta cada segundo y devuelve un identificador que se usa para detener estas llamadas cuando se alcanza la fecha límite a través de la función clearInterval.

Indica el valor de las marcas @1, @2 y @3 para que el código anterior funcione como se ha indicado.

Problema

El siguiente código permite jugar en el navegador a una versión muy simplificada del juego del dinosaurio al que se puede jugar en Google Chrome cuando no se puede mostrar la página solicitada por falta de conexión (pregunta al profesor por la dinámica de este juego si no lo conoces). En este caso, al hacer clic en el botón izquierdo del ratón o pulsar cualquier tecla, el dinosaurio se desplaza de golpe (es decir, no suavemente) a una posición superior y vuelve al nivel del suelo pasado medio segundo. Se crea un nuevo cactus cada 2 segundos que se va desplazando desde la derecha de la zona de juego a la izquierda; el dinosaurio, por otro lado, no se desplaza horizontalmente desde su posición inicial a la izquierda.

<!DOCTYPE html>
<html>
  <head>
    <title>Simple Dino Game</title>
    <style>
      #game {
        position: relative;
        height: 200px;
        width: 500px;
        border: 1px solid black;
      }
      .dino {
        position: absolute;
        height: 20px;
        width: 20px;
        font-size: 20px;
        bottom: 0;
        transform: scale(-1, 1); /* flip the dino to look right */
      }
      .cactus {
        position: @1;
        height: 20px;
        width: 20px;
        font-size: 20px;
        bottom: 0;
        right: -20px;
      }
    </style>
  </head>
  <body>
    <div id="game">
      <div class="dino" id="dino">🦖</div>
    </div>

    <script>
      var dino = document.getElementById('dino');
      var game = document.getElementById('game');
      var jumping = 0;
      var obstacles = [];

      document.addEventListener('keydown', function (e) {jump();});
      document.addEventListener('click', function (e) {jump();});

      function jump() {
        if (jumping == 0) {
          jumping = 1;
          dino.style.bottom = '100px';

          setTimeout(function () {
            @2 = '0';
            jumping = 0;
          }, 500);
        }
      }

      // create new obstacles every 2 seconds
      setInterval(function () {
        var cactus = document.createElement('div');
        cactus.classList.add('cactus');
        cactus.style.right = '0';
        cactus.textContent = "🌵";
        game.@3(cactus);

        setInterval(function () {
          if (cactus.textContent == "") return;
          var boxPos = parseInt(dino.style.bottom);
          var obsPos = parseInt(cactus.style.right);

          if (obsPos > 480 && obsPos < 520 && boxPos <= 20) {
            alert('Game Over!');
            cactus.remove();
            cactus.textContent = "";
          } else {
            cactus.style.right = obsPos + 2 + 'px';
          }
        }, 10);
      }, 2000);
    </script>
  </body>
</html>

Indica con qué sustituir las marcas @1, @2 y @3 para que el juego funcione correctamente.

Problema

Considera que el tiempo de ejecución de cualquier instrucción del siguiente código es no nulo pero virtualmente infinitesimal. La función setTimeout es estándar de JavaScript y registra una función que se ejecutará asíncronamente después del número de milisegundos indicados como segundo parámetro. Indica cuál es la salida del siguiente programa.

function t(i) {
  if (i<=0) {
    return;
  }
  else if (i%2===1) {
    setTimeout(() => console.log(i), 5000-i*100);
  }
  else {
    setTimeout(() => console.log(i), 5000+i*100);
  }
  t(i-1)
}

t(1); t(6); t(1);

Problema

Considera este código de JavaScript:

function Character(name, house) {
  this.name = name;
  this.house = house;
}

Character.@1.sayHello = function() {
  console.log(`Hello, my name is ${this.name} and I belong to ${this.house} house.`);
}

function Wizard(name, house, pet, wand) {
  this.character = new Character(name, house);
  this.pet = pet;
  this.wand = wand;
}

Wizard.prototype.sayHello = function() {
  this.character.sayHello();
}

Wizard.prototype.presentPet = function() {
  console.log(`My pet is a ${this.pet.species}, and its name is ${this.pet.petName}.`);
}

Wizard.prototype.waveWand = function() {
  console.log(`Waving my ${this.wand} wand!`);
}

function Pet(petName, species) {
  this.petName = petName;
  this.species = species;
}

@2.hogwartsSchool = 'Hogwarts School of Witchcraft and Wizardry'; // static property

Pet.prototype.makeSound = function() {
  if (this.species === 'owl') {
    console.log('Who who!');
  } else if (this.species === 'cat') {
    console.log('Meow!');
  } else if (this.species === 'toad') {
    console.log('Ribbit!');
  } else {
    console.log('I make an unknown sound!');
  }
}

var hedwig = new Pet('Hedwig', 'owl');
var harry = new Wizard('Harry Potter', 'Gryffindor', hedwig, 'Holly, 11", phoenix feather');

harry.sayHello();
harry.presentPet();
harry.waveWand();
console.log(`I study at ${Wizard.hogwartsSchool}.`);
hedwig.makeSound();

var crookshanks = new Pet('Crookshanks', 'cat');
var hermione = new Wizard('Hermione Granger', 'Gryffindor', crookshanks, 'Vine wood, 10¾", dragon heartstring');

hermione.sayHello();
hermione.presentPet();
hermione.waveWand();
console.log(`I study at ${Wizard.hogwartsSchool}.`);
crookshanks.makeSound();

El código anterior crea diversos objetos en JavaScript e imprime lo siguiente en consola:

Hello, my name is Harry Potter and I belong to Gryffindor house.
My pet is a owl, and its name is Hedwig.
Waving my Holly, 11", phoenix feather wand!
I study at Hogwarts School of Witchcraft and Wizardry.
Who who!
Hello, my name is Hermione Granger and I belong to Gryffindor house.
My pet is a cat, and its name is Crookshanks.
Waving my Vine wood, 10¾", dragon heartstring wand!
I study at Hogwarts School of Witchcraft and Wizardry.
Meow!

Indica el valor de las marcas @1 y @2 para que el código anterior funcione como se ha indicado.

8.4. Acceso a servicios web de terceros

Problema

Sabiendo que no hay ningún error en el siguiente código, indica la salida que emite por consola el siguiente bloque de JavaScript:

 1p1()
 2.then( (x) => { console.log(x*x); return p2(x+1,x+2,x+3); } )
 3.then( (x) => { console.log(x.a+x.b); x.a++; return true; } )
 4.catch( (x) => console.log(x.a*x.b) );
 5
 6function p1() {
 7  return new Promise( (resolve,reject) => resolve(2) );
 8}
 9
10function p2(a,b) {
11  return new Promise( (resolve,reject) => reject( {a:a,b:a*b} ) );
12}

Problema

Sabiendo que no hay ningún error en el siguiente código, indica con qué valor hay que sustituir las expresiones @1 y @2 en el siguiente código para que la salida emitida por consola sea 5:

 1new Promise( (resolve,reject) => resolve( {a:0,b:2} ) )
 2.then( (x) => {
 3  return new Promise (
 4    function (resolve,reject) {
 5      if (x.a+5===@1 && x.b*x.b*x.b===@2) {
 6        resolve(x.a+5);
 7      }
 8      else {
 9        reject(x.b+2);
10      }
11    }
12  )
13})
14.then( (x) => console.log(x) )
15.catch( (x) => console.log(x) );

Problema

Indica cuál es la salida del siguiente programa en JavaScript.

 1new Promise(function(resolve, reject) {
 2  setTimeout(() => resolve(1), 1000);
 3}).then(function(result) {
 4  console.log(result);
 5  return new Promise((resolve, reject) => { // (*)
 6    setTimeout(() => resolve(result * 2), 1000);
 7  });
 8}).then(function(result) { // (**)
 9  console.log(result);
10  return new Promise((resolve, reject) => {
11    setTimeout(() => resolve(result * 2), 1000);
12  });
13}).then(function(result) {
14  console.log(result);
15});

Problema

Teníamos un fragmento correcto de código en JavaScript que realizaba una petición asíncrona a http://example.com/movies.json/birdbox y mostraba por consola el valor del atributo title de los datos en JSON devueltos por el servidor. Lamentablemente, las líneas de nuestro programa se han desordenado y, además, mezclado con líneas de otros programas. Indica la secuencia de líneas, de entre las siguientes, que permiten reconstruir el programa original. Una posible respuesta (incorrecta) sería 03,09,04.

01    .then(function(r) {
02    .then(
03    })
04    console.log(title);
05    .then(title)
06    console.log(movie.title);
07    .then(function(movie) {
08    console.log(r.json().title);
09    });
10    fetch('http://example.com/movies.json/birdbox')
11    return r.json();
12    fetch(function('http://example.com/movies.json/birdbox'))

Problema

Sabiendo que no hay ningún error en el siguiente código y que la llamada al URL indicado en fetch devuelve en el cuerpo de la respuesta el dato válido en JSON {"title":"天気の子","director":"新海誠","year":2019}, indica el código con el que hay que sustituir @1 y @2 en el siguiente bloque de JavaScript para que se imprima por consola el valor 2021:

 1async function movie() {
 2  var g= 1;
 3  g+= @1;
 4  try {
 5    let r= await fetch('http://example.com/movies.json/3400231');
 6    let x= @2 r.json();
 7    console.log(x.year + g);
 8  } catch(e) {
 9    console.log(e)
10  };
11}
12
13movie();

Problema

Indica los tres errores de formato que hay en la representación en JSON del siguiente dato y cómo los solucionarías con la menor cantidad de modificaciones.

 1{
 2  "name": "Duke",
 3  age: 18,
 4  "streetAddress": "100 Internet Dr",
 5  "city":"New York",
 6  "married": true
 7  "sex": male,
 8  "companies": [],
 9  "universities": [{}  ],
10  "phoneNumbers": [
11    { "Mobile": "1111111111" },
12    { "Mobile": 2222222222 },
13    33333
14  ]
15}

Problema

Indica con qué sustituir @1 y @2 en el siguiente código para que delay defina una alternativa a setTimeout basada en promesas.

1function delay(ms) {
2  return new Promise(resolve => setTimeout(@1,@2));
3}
4
5// ejemplo de uso:
6delay(3000).then(() => console.log('esto se imprime tras 3 segundos'));

Problema

Sabiendo que no hay ningún error en el siguiente código y que la llamada al URL indicado en fetch devuelve en el cuerpo de la respuesta el dato válido en JSON {"title":"天気の子","director":"新海誠","year":2019}, indica la salida que emite por consola el siguiente bloque de JavaScript:

function movie() {
  var g= 1;
  fetch('http://example.com/movies.json/3400231')
  .then( r => {
    g++;
    return r.json();
  })
  .then( x => {
    g++;
    console.log(x.year+g);
  })
  .catch( e => console.log(e) );
  g++;
  console.log(g);
}

movie();

Problema

Una petición GET al URL https://api.coindesk.com/v1/bpi/currentprice.json devuelve siempre la siguiente información en formato JSON:

 1{
 2    "time":{
 3      "updated":"Jul 1, 2021 15:11:00 UTC",
 4      "updatedISO":"2021-07-01T15:11:00+00:00",
 5      "updateduk":"Jul 1, 2021 at 16:11 BST"
 6    },
 7    "disclaimer":"This data was produced from the CoinDesk Bitcoin Price Index (USD).",
 8    "chartName":"Bitcoin",
 9    "bpi":{
10      "USD":{
11          "code":"USD",
12          "symbol":"&#36;",
13          "rate":"33,472.6400",
14          "description":"United States Dollar",
15          "rate_float":33472.64
16      },
17      "GBP":{
18          "code":"GBP",
19          "symbol":"&pound;",
20          "rate":"24,289.1200",
21          "description":"British Pound Sterling",
22          "rate_float":24289.12
23      },
24      "EUR":{
25          "code":"EUR",
26          "symbol":"&euro;",
27          "rate":"28,203.4774",
28          "description":"Euro",
29          "rate_float":28203.47
30      }
31    }
32}

Considera el siguiente código en JavaScript:

 1async function euro() {
 2    fetch("https://api.coindesk.com/v1/bpi/currentprice.json")
 3    .then(response => response.json())
 4    .then(data => console.log(data.bpi.EUR.rate_float));
 5}
 6
 7function libra() {
 8    fetch("https://api.coindesk.com/v1/bpi/currentprice.json")
 9    .then(response => response.json())
10    .then(data => console.log(data.bpi.GBP.rate_float));
11}
12
13function dollar() {
14    fetch("https://api.coindesk.com/v1/bpi/currentprice.json")
15    .then(response => response.json())
16    .then(data => console.log(data.bpi.USD.rate_float));
17}
18
19async function main() {
20    dollar();
21    await euro();
22    libra();
23}
24
25main();

Indica cuál o cuáles de las salidas siguientes es imposible que se produzca por consola (independientemente del estado de la conexión a internet) al ejecutar el programa anterior:

  1. 33472.64 28203.47 24289.12

  2. 33472.64 24289.12

  3. 28203.47 33472.64 24289.12

  4. 24289.12 28203.47 33472.64

  5. 28203.47 24289.12 33472.64

Indica el número o números de línea que corresponden con la respuesta. Si ninguna de las salidas es viables, indica ninguna.

Problema

Indica qué poner en @1, @2 y @3 para que el siguiente comic sobre CORS de la web wizardzines.com de Julia Evans esté completo y la información sea correcta:

CORS

Problema

Indica qué poner en @1, @2 y @3 para que el siguiente comic sobre peticiones HTTP de la web wizardzines.com de Julia Evans esté completo y la información sea correcta:

peticiones HTTP

Problema

El siguiente código en JavaScript crea tres objetos de tipo promesa y después utiliza el método Promise.all para ejecutarlas todas a la vez. Este método, ya definido en la clase Promise de la librería de JavaScript, devuelve una promesa que se resuelve (esto es, se cumple) cuando todas las promesas pasadas en un array como argumento se han resuelto. Si todas las promesas se cumplen, la promesa devuelta por Promise.all se cumple con un array que contiene los valores de las promesas cumplidas. Si alguna de las promesas se rechaza, la promesa devuelta por Promise.all se rechaza con el motivo de la promesa que se rechazó; en el caso de que se rechace más de una promesa, la promesa devuelta por Promise.all se rechaza con el motivo de la primera promesa que se haya rechazado.

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (flag)
      resolve(1);
    else
      @1(1);
  }, 5000);
});

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (flag)
      @2(2);
    else
      @3(2);
  }, 3000);
});

const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(3);
  }, 2000);
});

Promise.all([p3, @4, p1, p3]).then(values => {
  values.forEach(value => console.log(value));
}).catch(console.log);

Indica con qué sustituir las marcas @1, @2, @3 y @4 para que el código anterior imprima solo un 2 por consola cuando la variable global flag sea verdadera y más de un valor cuando la variable flag sea falsa.

Problema

La respuesta de este problema tiene que ver con la función Promise.all discutida en el problema anterior, aunque no es necesario haber resuelto aquel para resolver este problema. Se propone la siguiente implementación de la función all (llamada aquí my_all), que aunque presenta alguna carencias respecto a la implementación de la librería de JavaScript, es suficiente para funcionar correctamente en el caso de uso del problema anterior:

function my_all(promises) {
  return new Promise((resolve, reject) => {
    let resolvedCounter = 0;
    let resolvedValues = [ ];
    for (let i = 0; i < promises.length; i++) {
      promises[i]
      .then(value => {
        resolvedCounter++;
        resolvedValues[i] = @1;
        if (resolvedCounter == @2) {
          resolve(resolvedValues);
        }
      })
      .catch(value => reject(value));
    }
  });
}

Indica con qué sustituir @1 y @2 para que el código anterior corresponda a una implementación adecuada de Promise.all.

Problema

El siguiente código en JavaScript crea tres objetos de tipo promesa y después utiliza el método inventado Promise.allBefore (que no existe en el API oficial de la clase Promise) para activarlas todas a la vez. Este método devuelve una promesa que se resuelve (esto es, se cumple) cuando todas las promesas pasadas en un array en su primer argumento se han resuelto antes de los tiempos indicados para cada una en la lista del segundo argumento. Si todas las promesas se cumplen, la promesa devuelta por Promise.allBefore se cumple con un array que contiene los valores de las promesas cumplidas. Si alguna de las promesas se rechaza, la promesa devuelta por Promise.allBefore se rechaza con el motivo de la promesa que se rechazó; en el caso de que se rechace más de una promesa, la promesa devuelta por Promise.allBefore se rechaza con el motivo de la primera promesa que se haya rechazado.

let promise1 = new Promise((@1, reject) => {
    setTimeout(@2, 2000, '⛅');
});

let promise2 = new Promise((@1, reject) => {
    setTimeout(@2, 1000, '🌞');
});

let promise3 = new Promise((@1, reject) => {
    setTimeout(@2, 3000, '🌙');
});

Promise.allBefore([promise1, promise2, promise3], [2500, 1500, 3500])
    .then((values) => {
        console.log(values);
    })
    .catch((error) => {
        console.error(error);
    });

Observa que la promesa devuelta por la llamada a allBefore anterior se termina cumpliendo, pero no sería así si cambiáramos 2000 por 4000.

Los argumentos de setTimeOut del tercero en adelante son argumentos que se pasan a la función que se ejecuta cuando se cumple el tiempo indicado.

Indica con qué sustituir las marcas @1 y @2 para que el código anterior imprima, en este orden, los emojis 🌞 ⛅ 🌙.

Problema

La respuesta de este problema tiene que ver con la función Promise.allBefore discutida en el problema anterior, aunque no es necesario haber resuelto aquel para resolver este problema. Se propone la siguiente implementación de la función allBefore, que funciona correctamente en el caso de uso del problema anterior:

Promise.allBefore = function (promises, milliseconds) {
    return new Promise((resolve, reject) => {
        let results = [];
        let count = 0;

        if (promises.length !== milliseconds.length) {
            throw new Error('Error: los arrays no tienen la misma longitud');
        }

        promises.forEach((promise, index) => {
            let timer = setTimeout(() => {
                @1(`La Promesa en el índice ${index} no se resolvió en el tiempo especificado.`);
            }, @2);

            promise.then(result => {
                clearTimeout(timer);
                results[index] = result;
                count++;

                if (@3) {
                    resolve(results);
                }
            }).catch(error => {
                clearTimeout(timer);
                reject(error);
            });
        });
    });
};

Indica con qué sustituir @1, @2 y @3 para que el código anterior corresponda a una implementación adecuada de Promise.allBefore.

8.5. Componentes web

Problema

Considera el siguiente fichero index.html:

 1<!DOCTYPE html>
 2<html>
 3<head>
 4  <meta charset="utf-8">
 5  <title>Mi componente</title>
 6  <script src="micomp.js" defer></script>
 7  <style>
 8    :host {
 9      color: mintcream;
10    }
11    p.m {
12      color: papayawhip;
13    }
14  </style>
15</head>
16<body>
17  <h1>Mi componente</h1>
18
19  <template id="mi-componente">
20    <style>
21      p {
22        color: navajowhite;
23      }
24    </style>
25    <p class="m"><slot name="mi-texto">Texto por defecto</slot></p>
26  </template>
27
28  <mi-componente>
29    <span slot="mi-texto">En un agujero en el suelo, vivía un hobbit.</span>
30  </mi-componente>
31
32  <mi-componente>
33    No un agujero
34      <ul slot="mi-texto">
35        <li>húmedo, sucio, repugnante, con restos de gusanos
36            y olor a fango,</li>
37        <li>ni tampoco un agujero seco, desnudo y arenoso,
38            sin nada en que sentarse o que comer:</li>
39      </ul>
40    era un agujero-hobbit, y eso significa comodidad.
41  </mi-componente>
42
43</body>
44</html>

Considera también el contenido del fichero micomp.js:

 1customElements.define('mi-componente',
 2  class extends HTMLElement {
 3    constructor() {
 4      super();
 5
 6      const template = document.getElementById('mi-componente');
 7      const templateContent = template.content;
 8
 9      this.attachShadow({mode: 'open'}).appendChild(
10        templateContent.cloneNode(true)
11      );
12    }
13  }
14);

Enumera en qué colores se muestran las palabras suelo, fango y comodidad. Si la palabra no se muestra en el documento web, o no puedes saber su color, indica ninguno. Una posible respuesta (incorrecta) sería: red, ninguno, blue.

Problema

Considera el contenido del fichero invierte-cadena.js que define un componente web que muestra invertida y en color azul la cadena recibida como parámetro:

 1(function() {
 2  const template = document.createElement('template');
 3
 4  template.innerHTML = `
 5    <style>
 6      p {
 7        color: steelblue;
 8      }
 9    </style>
10    <p @1></p>`;
11
12  function reverse(s) {
13    return s.split("").reverse().join("");
14  }
15
16  class ReverseString extends HTMLElement {
17    constructor() {
18      super();
19      let clone = template.content.cloneNode(true);
20      let shadowRoot = this.attachShadow({mode: 'open'});
21      shadowRoot.appendChild(clone);
22    }
23
24    connectedCallback() {
25      this.s= !this.hasAttribute('s')?"":this.getAttribute(@2);
26      this.shadowRoot.querySelector('#cadena').textContent= reverse(@3);
27    }
28  }
29
30  customElements.define("invierte-cadena", ReverseString);
31
32})();

Un posible uso del componente web en un documento HTML sería:

1<invierte-cadena s="hola"></invierte-cadena>

Indica con qué sustituir las marcas @1, @2 y @3 del código anterior para que el componente web funcione correctamente.

Problema

Dibuja cómo se muestra en el navegador el siguiente bloque de un documento HTML cuando el cursor del ratón no está situado en ninguno de los elementos con id w1 o w2, y cuando se sitúa sobre el elemento con id w2. La imagen rain.png contiene el icono rain y sun.png contiene sun.

1<h1>El tiempo</h1>
2<ul>
3  <li>Lunes <mysterious-element data-img="rain.jpg"
4              data-text="Chubascos a primera hora de la mañana que desaparecerán
5              por la tarde." id="w1"></mysterious-element></li>
6  <li>Martes <mysterious-element data-img="sun.png" data-text="Soleado todo el día."
7              id="w2"></-info></li>
8</ul>
9<script defer src="mysterious-element.js">

El fichero mysterious-element.js define el componente web y su contenido es el siguiente:

 1class PopUpInfo extends HTMLElement {
 2  constructor() {
 3    super();
 4
 5    const shadow = this.attachShadow({mode: 'open'});
 6    const wrapper = document.createElement('span');
 7    wrapper.setAttribute('class', 'wrapper');
 8
 9    const icon = document.createElement('span');
10    icon.setAttribute('class', 'icon');
11    this.info = document.createElement('span');
12    this.info.setAttribute('class', 'info');
13
14    this.img = document.createElement('img');
15    icon.appendChild(this.img);
16
17    const style = document.createElement('style');
18
19    style.textContent = `
20      .wrapper {
21        position: relative;
22        margin: 4px;
23      }
24
25      .info {
26        font-size: 0.8rem;
27        width: 200px;
28        display: inline-block;
29        border: 1px solid black;
30        padding: 10px;
31        background: white;
32        border-radius: 10px;
33        opacity: 0;
34        position: absolute;
35        bottom: 20px;
36        left: 10px;
37        z-index: 3;
38      }
39
40      img {
41        width: 1.1em;
42      }
43
44      .icon:hover + .info, .icon:focus + .info {
45        opacity: 1;
46      }
47    `;
48
49    shadow.appendChild(style);
50    shadow.appendChild(wrapper);
51    wrapper.appendChild(icon);
52    wrapper.appendChild(this.info);
53  }
54  connectedCallback() {
55    let text = this.getAttribute('data-text');
56    this.info.textContent = text;
57    let imgUrl = this.getAttribute('data-img');
58    this.img.src = imgUrl;
59  }
60}
61
62customElements.define('popup-info', PopUpInfo);

La propiedad de CSS opacity permite definir el grado de transparencia del contenido en una escala de 0 a 1. Un valor de 0 produce un efecto similar a visibility:hidden, excepto porque esto último no consume eventos de ratón (como el clic, por ejemplo).

Problema

Indica cuál o cuáles de las siguientes afirmaciones son ciertas. Si ninguna lo es, pon ninguna como respuesta. Justifica muy esquematicamente en el espacio correspondiente los motivos por los que has considerado cada afirmación como verdadera o falsa.

  1. Para usar la técnica CORS, es necesario que desde nuestro código en JavaScript (por ejemplo, al llamar a la función fetch) se le dé un valor adecuado a la cabecera Origins.

  2. La política del mismo origen (same-origin policy) es una restricción implementada hoy en día por todos los servidores web, aunque el servidor web de Apache fue el primero en hacerlo.

  3. La tecnología del DOM ensombrecido (shadow DOM) permite crear un subárbol DOM relativamente aislado del árbol DOM global; decimos relativamente porque, por ejemplo, algunas propiedades de CSS provenientes de fuera del shadow DOM se pueden heredar dentro de este.

  4. Aunque el estándar HTML indica que desde el constructor de un componente web no se debería poder acceder a los atributos del elemento, algunos navegadores permiten hacerlo.

  5. La versión 3 de HTTP se apoya en un protocolo de transporte llamado QUIC.

Problema

Considera el siguiente código que define e instancia un componente web que muestra tres emojis diferentes y un contador bajo cada uno de ellos que se incrementa al hacer clic sobre el emoji correspondiente. El contador se inicializa a cero salvo que se dé un valor al atributo init al instanciar el componente.

<!DOCTYPE html>
<html>
  <body>
    <emoji-reaction init="2"></emoji-reaction>

    <script>
      class EmojiReaction extends HTMLElement {
        constructor() {
          super();

          this.sadCount = this.getAttribute('init') @1 0;
          this.happyCount = this.getAttribute('init') @1 0;
          this.laughCount = this.getAttribute('init') @1 0;

          this.emojiMap = {
            '😞': this.sadCount,
            '😀': this.happyCount,
            '😂': this.laughCount,
          };

          this.shadow = this.attachShadow({ mode: 'open' });
        }

        connectedCallback() {
          this.render();
          @2;
        }

        render() {
          this.shadow.innerHTML = `
            <style>
              .emoji-container {
                display: flex;
                justify-content: space-around;
                align-items: center;
                padding: 1em;
                background-color: #f0f0f0;
                border-radius: 1em;
                box-shadow: 0px 0px 10px rgba(0,0,0,0.15);
              }
              .emoji-item {
                text-align: center;
                cursor: pointer;
              }
            </style>
            <div class="emoji-container">
              ${Object.entries(this.emojiMap)
                .map(
                  ([emoji, count]) =>
                    `<div @3>
                      <div class="emoji">${emoji}</div>
                      <div class="count">${count}</div>
                    </div>`
                )
                .join('')}
            </div>
          `;
        }

        registerEventListeners() {
          this.shadow.querySelectorAll('.emoji-item').forEach((item) => {
            item.addEventListener('click', (e) => {
              const emoji = e.currentTarget.querySelector('.emoji').textContent;
              this.incrementCount(emoji);
            });
          });
        }

        incrementCount(emoji) {
          this.emojiMap[emoji]@4;
          this.render();
          this.registerEventListeners();
        }
      }

      window.customElements.define('emoji-reaction', EmojiReaction);
    </script>
  </body>
</html>

La función Object.entries devuelve un array de arrays con las parejas clave-valor de un objeto. Por ejemplo, Object.entries({ a: 1, b: 2 }) devuelve [['a', 1], ['b', 2]]. La función join une los elementos de un array en una cadena separándolos por el carácter que se le pasa como argumento. Por ejemplo, ['a', 'b', 'c'].join('-') devuelve 'a-b-c'. La función map aplica una función a cada elemento de un array y devuelve un array con los resultados. Por ejemplo, [1, 2, 3].map((x) => x * 2) devuelve [2, 4, 6].

No necesitas conocer esto para resolver este problema, pero la propiedad display:flex de CSS permite definir un contenedor flexible que alinea sus elementos hijos de forma horizontal o vertical; la propiedad justify-content: space-around permite distribuir los elementos hijos de un contenedor flexible de forma que haya el mismo espacio entre ellos; y la propiedad align-items: center permite alinear verticalmente los elementos hijos de un contenedor flexible.

Sustituye @1, @2, 3 y @4 por las cadenas necesarias para que el componente web se comporte correctamente.

8.6. Implementación de servicios web

Problema

El siguiente código define una función de middleware de Express que añade la cabecera Content-type con valor text/html a la respuesta del servidor. Indica con qué hay que sustituir @1 y @2 para que el código sea correcto.

1app.use( (request,response,foo) => {
2  res.set('Content-Type', '@1')
3  @2;
4});

Problema

Indica qué cadena ha de devolver en el bloque de datos la llamada al servicio web para que la salida emitida por consola sea zz80. Como siempre indica la respuesta más corta posible si hay más de una alternativa; si tu respuesta estuviera escrita en un formato (como HTML, CSS o JSON) que puede ser validado, asegúrate de que es válida.

 1function catalog() {
 2  fetch('http://example.com/service.json/discover/azz3').
 3  .then( r => {
 4    return r.json();
 5  })
 6  .then( x => {
 7    if (x.bool) {
 8      console.log(x.i+x.i-x.j);
 9    } else {
10      console.log(x.i+x.i+x.j);
11    }
12  })
13  .catch( e => console.log(e) );
14}
15
16catalog();

Problema

Indica con qué sustituir las marcas @1, @2 y @3 en el siguiente texto para que sea correcto: «El framework @1 de Node.js nos permite definir lo que en inglés se conoce como middleware. El middleware está formado por @2 encadenadas que se ejecutan durante el ciclo de vida de una petición al servidor. Cada una de ellas puede acceder a sendos objetos que representan la petición y la @3.»

Problema

Tenemos una aplicación web desplegada en example.com. El código que se ejecuta en el servidor está en el fichero index.js y es el siguiente:

 1const express = require('express');
 2const bodyParser = require('body-parser');
 3var path = require('path');
 4
 5const app = express();
 6
 7app.use(bodyParser.json());
 8
 9app.get('/index', (req, res) => {
10  res.sendFile(path.join(__dirname,'index.html'));
11});
12
13app.get('/@1', (req, res) => {
14  res.send({"key":@2*2});
15});
16
17app.listen(3000, () => console.log('server started'));

El documento index.html que se sirve al cliente desde el código anterior es:

 1<!DOCTYPE html>
 2<html>
 3  <head>
 4    <meta charset="utf-8">
 5    <title>Key</title>
 6  </head>
 7  <body>
 8    <script>
 9      fetch('/@3')
10      .then(r => r.json())
11      .then(x => console.log(@4))
12      .catch(e => console.log(e));
13    </script>
14  </body>
15</html>

Indica con qué hay que sustituir las marcas @1, @2, @3 y @4 en los dos bloques anteriores para que si se intenta abrir en un navegador el URL example.com/index, en la consola del navegador se muestre el valor 42. Como restricción adicional, los valores de @2 y @4 no pueden ser constantes numéricas.

Problema

Considera el siguiente fragmento de un documento HTML y asume que la petición al endpoint indicado devuelve la cadena en JSON [1,2,3,4,5]:

 1<script>
 2  async function load(url) {
 3    let response = @1 fetch(url);
 4    if (response.status == 200) {
 5      return response.json();
 6    }
 7    throw new Error(response.status);
 8  }
 9
10  (@2 function(){
11    let x= @3 load('https://array.org/5/');
12    console.log(JSON.stringify(x[@4]));
13  })();
14</script>

Indica con qué sustituir @1, @2, @3 y @4 para que el código anterior muestra un 1 por consola.

Problema

Dado el siguiente código de JavaScript, indica con qué sustituir la marca @1 para que se muestre un 10 por consola:

1async function w() {
2  return 10;
3}
4
5function f() {
6  w() @1 console.log);
7}
8
9f();

Problema

Indica con qué sustituir @1, @2 y @3 en el siguiente código para que el servidor solo atienda peticiones de tipo POST que indiquen en sus cabeceras que los datos del payload están en formato JSON. En caso contrario, ha de devolver el código de estado 400 y un mensaje de error. La respuesta para @4 ha de usar la variable f de algún modo.

 1const express = require('express');
 2const app = express();
 3
 4var f = () => {
 5    return (rq, rs, nx) => {
 6    if (@1.headers['content-type'] !== 'application/json') {
 7        @2.send('Este servidor solo procesa datos en JSON');
 8    } else {
 9        @3
10    }
11    }
12}
13
14app.use(@4)
15
16app.post('/', (rq, rs) => {
17    rs.send('JSON recibido');
18})
19
20app.post('/message', (rq, rs, nx) => {
21    rs.send('JSON recibido');
22})
23
24app.listen(3000);

Problema

Express define un middleware por defecto que se encarga de la gestión de errores que se producen en otros middleware. Este tipo de middlewares tiene un prototipo diferente al de los otros middlewares al tener un primer parámetro adicional que representa el error:

1app.use((err, req, res, next) => {
2    // middleware de gestión del error
3})

El programador puede obviamente definir sus propios middlewares de gestión de errores. Para llamar a este tipo especial de middleware basta pasar un argumento a la llamada a la función next. Por ejemplo, el siguiente código pasa el testigo a un middleware de gestión de error definido por el programador cuando llega una petición GET al URL /open.

 1app.get('/open', (req, res, next) => {
 2    next(new Error('I am passing you an error!'));
 3});
 4
 5app.use((err, req, res, next) => {
 6    console.log(err);
 7    if(!res.headersSent){
 8    res.status(500).send(err.message);
 9    }
10});

Un middleware de gestión de error puede (de forma similar a los middlewares normales) llamar al siguiente middleware de gestión de error, generando así una cadena (pipeline) de llamadas. En última instancia, si el último middleware de la cadena definida por el programador llamará a la siguiente función con un argumento de error, se invocaría el middleware de gestión de error por defecto definido por Express.

El siguiente código para Express define tres funciones de middleware de gestión de errores. Si llega una petición a /nonexistant se devuelve al cliente el mensaje NotFound. Si llega una petición a /problematic se devuelve al cliente el mensaje Unauthorized. Cualquier otra situación de error detectada en otros middleware hace que se devuelva al cliente el mensaje UnknownError.

 1app.get('/nonexistant', (req, res, next) => {
 2    let err = new Error('I couldn\'t find it.');
 3    err.httpStatusCode = 404;
 4    next(@1);
 5});
 6
 7app.get('/problematic', (req, res, next) => {
 8    let err = new Error('I\'m sorry, you can\'t do that.');
 9    err.httpStatusCode = @2;
10    next(@1);
11});
12
13app.get(...);
14
15app.get(...);
16
17app.use((err, req, res, next) => {
18    if (err.httpStatusCode === 404) {
19    res.status(400).render('NotFound');
20    }
21    next(@3);
22});
23
24app.use((err, req, res, next) => {
25    if(err.httpStatusCode === 304){
26    res.status(304).render(@4);
27    }
28    next(@3);
29})
30
31app.@5((err, req, res, next) => {
32    console.log(err);
33    if (!res.headersSent) {
34    res.status(err.httpStatusCode || 500).render('UnknownError');
35    }
36});

Indica con qué sustituir @1, @2, @3, @4 y @5 en el código anterior para obtener la funcionalidad indicada.

Problema

El siguiente es el código de un servidor con Express con un único punto de acceso que devuelve un fragmento de HTML:

 1const express = require('express');
 2const cors = require('cors');
 3const app = express();
 4const port = 8080;
 5
 6app.use(cors());
 7
 8app.get('/', (req, res) => {
 9    res.send('a<strong>b</strong>c')
10});
11
12app.listen(port, () => {
13    console.log(`Listening at ${port}`);
14});

El paquete cors de Node.js permite en su forma más fácil (como la usada en el código anterior) tener un middleware que acepta todas las peticiones CORS independientemente de su origen.

Tras lanzar en nuestro ordenador el servicio anterior, creamos la página siguiente con la idea de probarlo:

 1<!DOCTYPE html>
 2<html lang="es">
 3<head><title>T</title></head>
 4<body>
 5    <div id="x"></div>
 6    <script>
 7    fetch('@1')
 8    .then(response => response.text())
 9    .then(@2 => {let x= document.querySelector("#x"); x.@3= response;})
10    </script>
11</body>
12</html>

Indica con qué sustituir @1, @2 y @3 en el código HTML anterior para que el navegador muestre la cadena abc con la letra b en negrita. Recuerda que la función text devuelve una promesa que se cumple si el cuerpo de la respuesta representada por el objeto receptor puede convertirse en una cadena de texto.

8.7. Computación en la nube

Problema

Indica con qué sustituir @1 en la siguiente frase para que sea correcta: «Los servicios de computación en la nube se pueden dividir en tres categorías en base al nivel de abstracción que ofrecen sobre los recursos utilizados: software como servicio, @1, e infraestructura como servicio»

Problema

Indica con qué sustituir las marcas @1 y @2 en el siguiente texto para que sea correcto: «Google Cloud Functions es un servicio de computación en la nube que permite ejecutar código de forma remota sin necesidad de lanzar una @1 explícita para ello, como sí ocurre con Google App Engine; ambos servicios son ejemplos de lo que se conoce en inglés como @2 as a service

Problema

Indica cuál o cuáles de las siguientes afirmaciones son ciertas. Si ninguna lo es, pon ninguna como respuesta.

  1. Google App Engine no es adecuado para aplicaciones cuya carga en cada momento es difícil de predecir.

  2. Cuando usamos Google App Engine no nos tenemos que preocupar de gestionar los servidores que ejecutan nuestro código, pero es posible que tengamos que configurar los servidores de las bases de datos.

  3. Las aplicaciones alojadas en Google App Engine escalan sus recursos automáticamente en base a la demanda.

  4. La plataforma Google App Engine es gratuita siempre que la aplicación no use ninguna base de datos.

Problema

Indica cuál o cuáles de las siguientes afirmaciones son ciertas. Si ninguna lo es, pon ninguna como respuesta.

  1. Las aplicaciones de Google App Engine pueden hacer llamadas a servicios externos usando sus APIs.

  2. Google App Engine realiza automáticamente el balanceo de carga de la aplicación.

  3. Una aplicación de Google App Engine puede usar Google Cloud Storage para almacenar archivos en línea.

  4. Las aplicaciones de Google App Engine pueden ser escritas en diferentes lenguajes de programación.

Problema

Indica cuál o cuáles de las siguientes afirmaciones son ciertas. Si ninguna lo es, pon ninguna como respuesta.

  1. Las instancias interrumpibles (preemptible en inglés) de Google Compute Engine pueden ser interrumpidas en cualquier momento sin nuestra autorización.

  2. Las instancias interrumpibles de Google Compute Engine no son adecuadas para tareas computacionalmente intensas cuya ejecución puede detenerse y reanudarse posteriormente.

  3. A la hora de decidir en qué región lanzamos una instancia de Google Compute Engine solo tenemos que fijarnos en el coste, ya que la latencia será la misma para los usuarios independientemente de la región.

  4. Dada una instancia detenida de Google Compute Engine, podemos cambiar la cantidad de memoria RAM de la que dispondrá cuando vuelva a lanzarse.

Problema

Indica con qué sustituir las marcas @1 y @2 en el siguiente texto para que sea correcto: «Las funciones de Google Cloud Functions pueden ser escritas en al menos estos dos lenguajes de programación: @1 y @2».

Problema

Indica cuál o cuáles de las siguientes afirmaciones son ciertas. Si ninguna lo es, pon ninguna como respuesta. Justifica muy esquemáticamente en el espacio correspondiente los motivos por los que has considerado cada afirmación como verdadera o falsa.

  1. Se denominan nubes públicas aquellos entornos de computación en la nube operados y controlados por un organismo público.

  2. Google Cloud Platform ofrece servicios para nubes públicas, privadas y mixtas.

  3. Se denominan nubes privadas aquellos entornos de computación en la nube que cualquiera puede utilizar, quizás previo pago, por internet.

  4. Una nube privada nunca ofrece servicios del tipo infrastructure as a service.

  5. Las arquitecturas serverless son más propias del modelo de computación en la nube conocido como platform as a service que del infrastructure as a service.

  6. Google App Engine integra un motor de base de datos, por lo que nunca es necesario para que nuestra aplicación de Google App Engine funcione lanzar instancias adicionales de máquinas virtuales en Google Cloud Platform.

Problema

Indica cuál o cuáles de las siguientes afirmaciones son ciertas. Si ninguna lo es, pon ninguna como respuesta. Justifica muy esquemáticamente en el espacio correspondiente los motivos por los que has considerado cada afirmación como verdadera o falsa.

  1. Es posible ejecutar múltiples imágenes al mismo tiempo basadas en un único contenedor de Docker.

  2. Por seguridad, un contenedor no puede acceder a archivos alojados en directorios del sistema anfitrión (host).

  3. Cada vez que ejecutamos docker build, la imagen se construye desde cero.

  4. La instrucción RUN de un Dockerfile sirve para ejecutar código dentro del sistema operativo de la imagen mientras esta se construye.

  5. Cuando usamos el servicio Google Cloud Build, la imagen resultante se almacena en una base de datos relacional dentro de Google Cloud SQL.

Problema

Tenemos toda una serie de aplicaciones desplegadas en Google Cloud Platform, algunas de las cuales almacenan ficheros en un bucket de Cloud Storage. Queremos ahora programar un servicio web que inserte en una tabla de una base de datos MySQL alojada en Cloud SQL la hora actual y el número de elementos almacenados en este momento en dicho bucket. Indica cuál o cuáles de las siguientes opciones constituye una posibilidad viable para ello, independientemente de su eficiencia o coste. Si ninguna lo es, indica ninguna como respuesta.

  1. Podríamos desplegar en Google App Engine una aplicación escrita en Java, que es uno de los lenguajes soportados por la plataforma, que obtenga mediante el API de Cloud Storage el número de elementos almacenados en el bucket y se conecte después a la base de datos de Cloud SQL para actualizar la tabla correspondiente. La aplicación expondría un servicio web que se ejecutaría en respuesta a una petición HTTP.

  2. Podríamos desarrollar una aplicación en Python que se ejecute en una instancia de Compute Engine y que se conecte a la base de datos de Cloud SQL y a Cloud Storage de forma similar a la alojada en Google App Engine. La instancia tendría los puertos necesarios abiertos para que se pudiera realizar peticiones HTTP a ella desde otras máquinas.

  3. Podríamos crear una función de Cloud Functions en JavaScript que se ejecute en respuesta a una petición web concreta. La función podría conectarse mediante el API correspondiente a Cloud Storage para obtener el número de elementos y a Cloud SQL para actualizar la base de datos.

  4. Podríamos escribir un fichero Dockerfile que cree una imagen que permita lanzar contenedores que incluyan un servidor PHP que ofrezca un servicio web que se ejecute en respuesta a una petición HTTP. El contenedor podría conectarse a la base de datos de Cloud SQL y a Cloud Storage mediante el API correspondiente. Podríamos utilizar Cloud Build para crear un flujo de integración que se ejecute cada vez que se realice un cambio en el código de nuestra aplicación de PHP. De esta manera, tendríamos siempre lista una imagen que podría ser desplegada en Cloud Run, que se encargará de crear y gestionar automáticamente los contenedores necesarios para ejecutar nuestra aplicación, así como proporcionar una URL pública para acceder a ella.

Problema

Indica con qué sustituir @1 y @2 en el siguiente fichero Dockerfile para que al usarlo con el programa docker se cree una imagen que permite lanzar contenedores que despliegan la aplicación web de Node.js formada por los ficheros index.html y app.js en el puerto 8080.

FROM node:14-alpine
WORKDIR /app
COPY package*.json ./
@1 npm install
@2 index.html .
@2 app.js .
EXPOSE 8080
CMD [ "npm", "start" ]